{
  "generatedFrom": "numbered-item.contract.json",
  "component": "Numbered item",
  "slug": "numbered-item",
  "group": "Settings",
  "tier": "leaf-lit",
  "summary": "The numbered wrapper for a repeatable composite item — a grey card with a muted number chip, a \"<Label> N\" header, a hover delete, and a body slot (SETTINGS-43).",
  "install": {
    "package": "@ahaslides-product/design",
    "registry": "https://npm.pkg.github.com",
    "scope": "@ahaslides-product",
    "auth": "Published to GitHub Packages — needs a GitHub token with read:packages. Configure the @ahaslides-product scope in .npmrc before installing.",
    "npmrc": "@ahaslides-product:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}   # a GitHub token with read:packages",
    "command": "npm i @ahaslides-product/design",
    "tokenLayer": "import '@ahaslides-product/design/tokens.css';",
    "import": "import '@ahaslides-product/design/aha-numbered-item';",
    "element": "aha-numbered-item",
    "registers": "aha-numbered-item"
  },
  "feeds": {
    "doc": "https://ahaslides-product.github.io/ahaslides-design/numbered-item/index.html",
    "md": "https://ahaslides-product.github.io/ahaslides-design/numbered-item/numbered-item.md",
    "agentJson": "https://ahaslides-product.github.io/ahaslides-design/numbered-item.agent.json",
    "llms": "https://ahaslides-product.github.io/ahaslides-design/numbered-item.llms.txt",
    "index": "https://ahaslides-product.github.io/ahaslides-design/llms.txt"
  },
  "recommendedSnippet": "html",
  "vibeCode": "Emit the HTML snippet by default — <aha-numbered-item> is a standard custom element that renders on open — React/Vue are thin adapters over the same element. Paste into an .html file and it renders with no build step.",
  "frameworks": {
    "react": {
      "via": "web-component",
      "ref": "aha-numbered-item"
    },
    "vue": {
      "via": "web-component",
      "ref": "aha-numbered-item"
    },
    "html": {
      "via": "web-component",
      "ref": "aha-numbered-item",
      "runnable": "paste-and-run — no build step, renders on open"
    }
  },
  "props": [
    {
      "name": "variant",
      "type": "contained | plain",
      "default": "contained",
      "desc": "contained = grey card (composite items); plain = no fill (single-field items only)"
    },
    {
      "name": "n",
      "type": "number",
      "default": "—",
      "desc": "The item's number, shown in the chip and the header"
    },
    {
      "name": "label",
      "type": "string",
      "default": "—",
      "desc": "Header noun — rendered as \"<Label> N\""
    },
    {
      "name": "deletable",
      "type": "boolean",
      "default": "false",
      "desc": "Show the hover delete; omit / false hides it entirely"
    },
    {
      "name": "candelete",
      "type": "boolean",
      "default": "true",
      "desc": "false disables the delete (at the minimum item count) without hiding it"
    },
    {
      "name": "collapsible",
      "type": "boolean",
      "default": "false",
      "desc": "Show a header caret that collapses the body in place (the QuestionList case)"
    },
    {
      "name": "delete",
      "type": "CustomEvent<{n}>",
      "default": "—",
      "desc": "Composed event when the delete is pressed; read e.detail.n"
    },
    {
      "name": "toggle",
      "type": "CustomEvent<{collapsed}>",
      "default": "—",
      "desc": "Composed event when the collapse caret is toggled; read e.detail.collapsed"
    }
  ],
  "tokens": [
    "bg-container-secondary",
    "bg-container-disabled",
    "bg-hover",
    "text-default",
    "text-secondary",
    "text-disabled",
    "icon-muted",
    "color-error",
    "radius-lg",
    "radius-sm",
    "radius-pill"
  ],
  "spec": [
    {
      "label": "Contained",
      "value": "whole item in ONE #F7F7F7 grey card, radius 12, no border, padding 12"
    },
    {
      "label": "Chip",
      "value": "22px muted-grey pill (#F1F1F1 / #4A4A4A), semibold 12 — never radical-purple"
    },
    {
      "label": "Header",
      "value": "chip + \"<Label> N\" title (semibold 14) + hover delete"
    },
    {
      "label": "Delete",
      "value": "tertiary text trash (system-trash), hover-only, space reserved; #F5222D on hover"
    },
    {
      "label": "deletable=false",
      "value": "the delete control is hidden entirely (non-removable item)"
    },
    {
      "label": "candelete=false",
      "value": "the delete is shown but disabled (minimum-count case)"
    },
    {
      "label": "Plain",
      "value": "no fill — for SINGLE-FIELD items only"
    }
  ],
  "opinion": {
    "whenToUse": [
      {
        "what": "Numbered item",
        "when": "a repeatable COMPOSITE item — more than one field, or a nested option list (a Question, a Card, a Round)"
      },
      {
        "what": "Option row",
        "when": "a flat list of single values — not wrapped in a numbered card"
      },
      {
        "what": "Plain variant",
        "when": "a single-field repeatable item that does not warrant a grey card"
      }
    ],
    "note": "This is the ONE exception to \"never a container around settings\" (SETTINGS-15): it wraps a repeatable composite item, not plain settings. A composite item must keep the contained grey card — dropping the fill (plain, or a hand-rolled header over a fill-less body) is a build mistake (SETTINGS-43). The chip is muted grey, never a purple badge.",
    "dsv3": "COVERED — the settings-lab NumberedItem control mapped into the DS. The grey card, muted chip and tertiary hover delete are the settings-specific composite-item wrapper (SETTINGS-43), reusing DS V3 secondary-fill + tertiary-button tokens."
  },
  "surfaces": [
    "editor",
    "settings"
  ],
  "snippets": {
    "html": "<!-- Paste-and-run: save as .html and open in a browser. No build step.\n     <aha-numbered-item> is the SAME shared custom element React and Vue consume — here in its native\n     form. Theming comes only from the --aha-* tokens in tokens.css. Hover an item to reveal its delete;\n     the whole item sits in ONE grey card (contained) with a muted-grey number chip. -->\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/tokens.css\">\n<script type=\"module\">\n  import 'https://cdn.jsdelivr.net/gh/ahaslides-product/ahaslides-design@master/lib/aha-numbered-item.js';   // registers <aha-numbered-item>\n</script>\n\n<div style=\"display:flex; flex-direction:column; gap:8px; max-width:420px\">\n  <aha-numbered-item n=\"1\" label=\"Question\" deletable id=\"q1\">\n    <div>The fields for question 1 go here (prompt, options, …).</div>\n  </aha-numbered-item>\n  <!-- candelete=\"false\" keeps the delete visible but disabled (e.g. at the minimum item count) -->\n  <aha-numbered-item n=\"2\" label=\"Question\" deletable candelete=\"false\">\n    <div>The fields for question 2 go here.</div>\n  </aha-numbered-item>\n</div>\n\n<script>\n  document.getElementById('q1').addEventListener('delete', (e) => console.log('delete item', e.detail.n));\n</script>\n",
    "react": "import '@ahaslides-product/design/aha-numbered-item'; // registers <aha-numbered-item>\nimport { useRef, useEffect } from 'react';\n\n// React 18 needs a thin wrapper; React 19 can use <aha-numbered-item> directly.\n// The item's fields are the children; onDelete fires when the hover trash is pressed.\nfunction AhaNumberedItem({ n, label, variant, deletable, canDelete, onDelete, children }) {\n  const ref = useRef();\n  useEffect(() => {\n    const el = ref.current;\n    const h = (e) => onDelete?.(e.detail.n);   // composed CustomEvent\n    el.addEventListener('delete', h);\n    return () => el.removeEventListener('delete', h);\n  }, [onDelete]);\n  return (\n    <aha-numbered-item\n      ref={ref}\n      n={String(n)}\n      label={label}\n      {...(variant ? { variant } : {})}\n      {...(deletable ? { deletable: '' } : {})}\n      {...(canDelete === false ? { candelete: 'false' } : {})}\n    >{children}</aha-numbered-item>\n  );\n}\n\n// usage\n<AhaNumberedItem n={1} label=\"Question\" deletable canDelete={items.length > 1} onDelete={removeQuestion}>\n  {/* the question's fields */}\n</AhaNumberedItem>\n",
    "vue": "// main.ts — register the element + mark aha-* as custom elements\nimport '@ahaslides-product/design/aha-numbered-item';   // registers <aha-numbered-item>\napp.config.compilerOptions.isCustomElement = (tag) => tag.startsWith('aha-');\n\n// Component.vue\n<script setup>\nimport { ref } from 'vue';\nconst questions = ref([{ id: 1 }, { id: 2 }]);\nfunction remove(n) { questions.value = questions.value.filter((_, i) => i + 1 !== n); }\n</script>\n\n<template>\n  <!-- the item's fields are the default slot; candelete disables (not hides) the trash at the min count -->\n  <aha-numbered-item\n    v-for=\"(q, i) in questions\"\n    :key=\"q.id\"\n    :n=\"String(i + 1)\"\n    label=\"Question\"\n    deletable\n    :candelete=\"questions.length > 1 ? 'true' : 'false'\"\n    @delete=\"remove($event.detail.n)\"\n  >\n    <div>Fields for question {{ i + 1 }}…</div>\n  </aha-numbered-item>\n</template>\n"
  }
}
