{
  "No.JS Conditional Block": {
    "prefix": "if",
    "body": [
      "<${1:div} if=\"${2:condition}\">",
      "\t$0",
      "</${1:div}>"
    ],
    "description": "No.JS conditional block with if directive"
  },
  "No.JS If/Else Block": {
    "prefix": "if-else",
    "body": [
      "<${1:div} if=\"${2:condition}\">",
      "\t${3:<!-- true content -->}",
      "</${1:div}>",
      "<${4:div} else>",
      "\t$0",
      "</${4:div}>"
    ],
    "description": "No.JS conditional block with if and else directives"
  },
  "No.JS Each Loop": {
    "prefix": "each",
    "body": [
      "<${1:li} each=\"${2:item} in ${3:items}\">",
      "\t<${4:span} bind=\"${2:item}.$5\"></${4:span}>",
      "</${1:li}>"
    ],
    "description": "No.JS each loop (alias of foreach)"
  },
  "No.JS Foreach Loop": {
    "prefix": "foreach",
    "body": [
      "<${1:li} foreach=\"${2:item} in ${3:items}\">",
      "\t<${4:span} bind=\"${2:item}.$5\"></${4:span}>",
      "</${1:li}>"
    ],
    "description": "No.JS foreach loop with inline template"
  },
  "No.JS For Loop": {
    "prefix": "for",
    "body": [
      "<${1:li} for=\"${2:item} in ${3:items}\">",
      "\t<${4:span} bind=\"${2:item}.$5\"></${4:span}>",
      "</${1:li}>"
    ],
    "description": "No.JS for loop (alias of foreach)"
  },
  "No.JS Foreach with Template": {
    "prefix": "foreach-template",
    "body": [
      "<${1:div} foreach=\"${2:item} in ${3:items}\" template=\"${4:item-tpl}\"></${1:div}>",
      "",
      "<template id=\"${4:item-tpl}\">",
      "\t<${5:span} bind=\"${2:item}.$6\"></${5:span}>",
      "</template>"
    ],
    "description": "No.JS foreach loop with external template"
  },
  "No.JS Foreach with Filter/Sort": {
    "prefix": "foreach-filter",
    "body": [
      "<${1:li} foreach=\"${2:item} in ${3:items}\" filter=\"${4:item.active}\" sort=\"${5:name}\" limit=\"${6:10}\">",
      "\t<${7:span} bind=\"${2:item}.$8\"></${7:span}>",
      "</${1:li}>"
    ],
    "description": "No.JS foreach loop with filter, sort, and limit"
  },
  "No.JS Inline Loop": {
    "prefix": "foreach-inline",
    "body": [
      "<${1:ul}>",
      "\t<${2:li} foreach=\"${3:item} in ${4:items}\">",
      "\t\t<${5:span} bind=\"${3:item}.$6\"></${5:span}>",
      "\t</${2:li}>",
      "</${1:ul}>"
    ],
    "description": "No.JS foreach with inline children as template (no template attr needed)"
  },
  "No.JS HTTP GET Fetch": {
    "prefix": "get",
    "body": [
      "<${1:div} get=\"${2:/api/endpoint}\" as=\"${3:data}\">",
      "\t<${4:span} bind-text=\"${3:data}.$5\"></${4:span}>",
      "</${1:div}>"
    ],
    "description": "No.JS HTTP GET fetch with data binding"
  },
  "No.JS HTTP GET with States": {
    "prefix": "get-full",
    "body": [
      "<${1:div} get=\"${2:/api/endpoint}\" as=\"${3:data}\">",
      "\t$0",
      "</${1:div}>",
      "",
      "<template id=\"${4:loading-tpl}\">",
      "\t<p>Loading...</p>",
      "</template>",
      "",
      "<template id=\"${5:error-tpl}\">",
      "\t<p>Error loading data</p>",
      "</template>"
    ],
    "description": "No.JS HTTP GET with loading and error templates"
  },
  "No.JS HTTP POST": {
    "prefix": "post",
    "body": [
      "<form post=\"${1:/api/endpoint}\" as=\"${2:result}\">",
      "\t<input name=\"${3:field}\" />",
      "\t<button type=\"submit\">Submit</button>",
      "</form>"
    ],
    "description": "No.JS HTTP POST form"
  },
  "No.JS Store Declaration": {
    "prefix": "store",
    "body": [
      "<div store=\"${1:myStore}\" value=\"{ ${2:key}: ${3:value} }\">",
      "\t$0",
      "</div>"
    ],
    "description": "No.JS store declaration with initial value"
  },
  "No.JS Config Stores": {
    "prefix": "config-stores",
    "body": [
      "<script>",
      "  NoJS.config({",
      "    stores: {",
      "      ${1:storeName}: { ${2:key}: ${3:value} }",
      "    }",
      "  });",
      "</script>"
    ],
    "description": "No.JS pre-initialize stores via config()"
  },
  "No.JS State": {
    "prefix": "state",
    "body": [
      "<${1:div} state=\"{ ${2:key}: ${3:value} }\">",
      "\t$0",
      "</${1:div}>"
    ],
    "description": "No.JS reactive state declaration"
  },
  "No.JS Form Validation": {
    "prefix": "form",
    "body": [
      "<form state=\"{ ${1:email}: '' }\" validate=\"\" error-class=\"${2:is-invalid}\" on:submit.prevent=\"${3:handleSubmit}\">",
      "\t<input name=\"${1:email}\" model=\"${1:email}\" validate=\"${4:required|email}\" />",
      "\t<span if=\"\\$form.errors.${1:email}\" bind=\"\\$form.errors.${1:email}\"></span>",
      "\t<button type=\"submit\" disabled=\"!\\$form.valid\">Submit</button>",
      "</form>"
    ],
    "description": "No.JS form with pristine-aware validation, error-class, and $form context (requires @erickxavier/nojs-elements plugin since v1.13.0)"
  },
  "No.JS Template": {
    "prefix": "template",
    "body": [
      "<template id=\"${1:my-template}\">",
      "\t$0",
      "</template>"
    ],
    "description": "No.JS reusable template"
  },
  "No.JS Use Template": {
    "prefix": "use",
    "body": [
      "<${1:div} use=\"${2:template-id}\"></${1:div}>"
    ],
    "description": "No.JS use a template by ID"
  },
  "No.JS Event Handler": {
    "prefix": "on",
    "body": [
      "<${1:button} on:${2:click}=\"${3:handler}\">${4:Click me}</${1:button}>"
    ],
    "description": "No.JS event handler"
  },
  "No.JS Bind Attribute": {
    "prefix": "bind",
    "body": [
      "<${1:div} bind-${2:text}=\"${3:expression}\"></${1:div}>"
    ],
    "description": "No.JS bind attribute directive"
  },
  "No.JS Route View": {
    "prefix": "route",
    "body": [
      "<route-view src=\"${1:pages/}\"></route-view>"
    ],
    "description": "No.JS route view component"
  },
  "No.JS i18n": {
    "prefix": "t",
    "body": [
      "<${1:span} t=\"${2:key}\">${3:fallback}</${1:span}>"
    ],
    "description": "No.JS internationalization text directive"
  },
  "No.JS HTTP Call": {
    "prefix": "call",
    "body": [
      "<${1:button} call=\"${2:/api/endpoint}\" method=\"${3:post}\" as=\"${4:data}\" loading=\"${5:loading-tpl}\">${6:Submit}</${1:button}>"
    ],
    "description": "No.JS HTTP call triggered by user action"
  },
  "No.JS HTTP Call with Confirm": {
    "prefix": "call-confirm",
    "body": [
      "<${1:button} call=\"${2:/api/endpoint}\" method=\"${3:delete}\" confirm=\"${4:Are you sure?}\" loading=\"${5:loading-tpl}\">${6:Delete}</${1:button}>"
    ],
    "description": "No.JS HTTP call with confirmation dialog"
  },
  "NoJS: 404 Catch-All Route": {
    "prefix": "nojs-route-404",
    "body": [
      "<template route=\"*\">",
      "\t<h1>404 — Page Not Found</h1>",
      "\t<p>The page <code bind=\"\\$route.path\"></code> does not exist.</p>",
      "\t<a route=\"/\">Go Home</a>",
      "</template>"
    ],
    "description": "Catch-all wildcard route template for 404 pages"
  },
  "No.JS Store Notify": {
    "prefix": "notify",
    "body": [
      "NoJS.notify(); // flush DOM bindings after store mutation"
    ],
    "description": "Call NoJS.notify() to trigger DOM updates after mutating NoJS.store from external JavaScript"
  },
  "No.JS Plugin (Object)": {
    "prefix": "plugin",
    "body": [
      "<script>",
      "  const ${1:myPlugin} = {",
      "    name: '${2:my-plugin}',",
      "    version: '1.0.0',",
      "    capabilities: ['${3:interceptors}'],",
      "",
      "    install(app, options) {",
      "      $0",
      "    },",
      "",
      "    init(app) {",
      "      // DOM is ready, router/stores available",
      "    },",
      "",
      "    dispose(app) {",
      "      // Cleanup: clear intervals, close connections",
      "    }",
      "  };",
      "",
      "  NoJS.use(${1:myPlugin});",
      "</script>"
    ],
    "description": "No.JS plugin with install, init, and dispose hooks. TypeScript definitions: types/nojs-plugin.d.ts"
  },
  "No.JS Plugin (Function Shorthand)": {
    "prefix": "plugin-fn",
    "body": [
      "<script>",
      "  function ${1:myPlugin}(app, options) {",
      "    $0",
      "  }",
      "",
      "  NoJS.use(${1:myPlugin});",
      "</script>"
    ],
    "description": "No.JS plugin using named function shorthand"
  },
  "No.JS Global Variable": {
    "prefix": "global",
    "body": [
      "<script>",
      "  NoJS.global('${1:name}', ${2:{ key: 'value' }});",
      "</script>"
    ],
    "description": "No.JS reactive global variable accessible as $name in expressions"
  },
  "No.JS Page Title": {
    "prefix": "page-title",
    "body": [
      "<div hidden page-title=\"${1:expression}\"></div>"
    ],
    "description": "No.JS head management: reactively set the document title"
  },
  "No.JS Page Description": {
    "prefix": "page-description",
    "body": [
      "<div hidden page-description=\"${1:expression}\"></div>"
    ],
    "description": "No.JS head management: reactively set meta description"
  },
  "No.JS Page Canonical": {
    "prefix": "page-canonical",
    "body": [
      "<div hidden page-canonical=\"${1:expression}\"></div>"
    ],
    "description": "No.JS head management: reactively set canonical URL"
  },
  "No.JS Page JSON-LD": {
    "prefix": "page-jsonld",
    "body": [
      "<div hidden page-jsonld>",
      "\t{ \"@type\": \"${1:Product}\", \"name\": \"{${2:product.name}}\" }",
      "</div>"
    ],
    "description": "No.JS head management: reactively set JSON-LD structured data"
  },
  "No.JS Head Management (All)": {
    "prefix": "page-head",
    "body": [
      "<div hidden page-title=\"${1:title}\"></div>",
      "<div hidden page-description=\"${2:description}\"></div>",
      "<div hidden page-canonical=\"${3:'/path/' + slug}\"></div>"
    ],
    "description": "No.JS head management: set title, description, and canonical URL"
  },
  "No.JS Plugin with Interceptor": {
    "prefix": "plugin-interceptor",
    "body": [
      "<script>",
      "  NoJS.use({",
      "    name: '${1:my-interceptor}',",
      "    install(app) {",
      "      app.interceptor('${2|request,response|}', (${3:url}, ${4:opts}) => {",
      "        $0",
      "        return ${4:opts};",
      "      });",
      "    }",
      "  });",
      "</script>"
    ],
    "description": "No.JS plugin that registers a request or response interceptor"
  },
  "No.JS Infinite Scroll": {
    "prefix": ["nojs-infinite-scroll", "nojs-scroll-pagination"],
    "body": [
      "<div get=\"${1:/api/items?page=\\{page\\}}\"",
      "     get-trigger=\"scroll\"",
      "     get-insert=\"append\"",
      "     get-page=\"${2:1}\"",
      "     as=\"${3:items}\">",
      "  <div each=\"${4:item} in ${3:items}\">",
      "    $0",
      "  </div>",
      "</div>"
    ],
    "description": "Infinite scroll with page-based pagination"
  },
  "No.JS Load More Button": {
    "prefix": ["nojs-load-more", "nojs-button-pagination"],
    "body": [
      "<div get=\"${1:/api/items?page=\\{page\\}}\"",
      "     get-trigger=\"button\"",
      "     get-trigger-label=\"${2:Load More}\"",
      "     get-insert=\"append\"",
      "     get-page=\"${3:1}\"",
      "     as=\"${4:items}\">",
      "  <div each=\"${5:item} in ${4:items}\">",
      "    $0",
      "  </div>",
      "</div>"
    ],
    "description": "Load more button with page-based pagination"
  },
  "No.JS Cursor Pagination": {
    "prefix": ["nojs-cursor-pagination", "nojs-cursor-scroll"],
    "body": [
      "<div get=\"${1:/api/items?cursor=\\{cursor\\}}\"",
      "     get-trigger=\"scroll\"",
      "     get-insert=\"append\"",
      "     get-cursor",
      "     get-cursor-field=\"${2:meta.nextCursor}\"",
      "     as=\"${3:items}\">",
      "  <div each=\"${4:item} in ${3:items}\">",
      "    $0",
      "  </div>",
      "</div>"
    ],
    "description": "Infinite scroll with cursor-based pagination"
  },
  "No.JS Lazy Load on Visible": {
    "prefix": ["nojs-lazy-visible", "nojs-visible-trigger"],
    "body": [
      "<div get=\"${1:/api/data}\"",
      "     get-trigger=\"visible\"",
      "     get-threshold=\"${2:200px}\"",
      "     as=\"${3:data}\">",
      "  $0",
      "</div>"
    ],
    "description": "Lazy load content when element becomes visible"
  },
  "No.JS Hover Prefetch": {
    "prefix": ["nojs-hover-prefetch", "nojs-hover-trigger"],
    "body": [
      "<div get=\"${1:/api/preview}\"",
      "     get-trigger=\"hover\"",
      "     as=\"${3:preview}\">",
      "  $0",
      "</div>"
    ],
    "description": "Prefetch content on hover"
  }
}
