{
  "version": 3,
  "sources": ["../src/index.ts"],
  "sourcesContent": ["import { define } from '@substrate-system/web-component'\nimport Debug from '@substrate-system/debug'\nconst debug = Debug('character-counter')\n\n// for document.querySelector\ndeclare global {\n    interface HTMLElementTagNameMap {\n        'character-counter': CharacterCounter\n    }\n}\n\n/**\n * <character-counter> - A visual character counter with circular progress\n *\n * Built without Shadow DOM following HTML-first principles. All styles are\n * defined in index.css and scoped with the custom element selector.\n *\n * Attributes:\n *   - max: Maximum character count (default: 300)\n *   - count: Current character count (default: 0)\n *   - hide-count: Boolean attribute - when present, never shows the remaining count text\n *   - warn: Boolean or number - when present as boolean, shows count when within 20 of limit;\n *           when set to a number, shows count when that many characters remain\n *           (has no effect if hide-count is present)\n *\n * CSS Custom Properties for theming:\n *   - --counter-diameter: Circle diameter (default: 2rem)\n *   - --counter-stroke-width: Circle stroke width (default: 3)\n *   - --counter-track-color: Background ring color (default: #e0e0e0)\n *   - --counter-normal-color: Progress color when under limit (default: #1d9bf0)\n *   - --counter-warning-color: Progress color when over limit (default: #f4212e)\n *   - --counter-text-color: Text color for remaining count (default: #536471)\n *\n * Data Attributes (set automatically):\n *   - data-over-limit: Present when count exceeds max\n *   - data-hide-count: Present when count text should be hidden (uses visibility: hidden)\n *\n * Usage:\n *   <character-counter max=\"300\" count=\"50\"></character-counter>\n *   <character-counter max=\"300\" count=\"50\" hide-count></character-counter>\n *   <character-counter max=\"300\" count=\"50\" warn></character-counter>\n *   <character-counter max=\"300\" count=\"50\" warn=\"50\"></character-counter>\n */\nexport class CharacterCounter extends HTMLElement {\n    static observedAttributes = ['max', 'count', 'hide-count', 'warn']\n    static TAG = 'character-counter'\n\n    get max ():number {\n        return parseInt(this.getAttribute('max') ?? '300', 10)\n    }\n\n    get count ():number {\n        return parseInt(this.getAttribute('count') ?? '0', 10)\n    }\n\n    set count (n) {\n        this.setAttribute('count', '' + n)\n    }\n\n    get hideCount ():boolean {\n        return this.hasAttribute('hide-count')\n    }\n\n    get warn ():boolean | number {\n        const value = this.getAttribute('warn')\n        if (value === null) return false\n        if (value === '') return true\n        const parsed = parseInt(value, 10)\n        return isNaN(parsed) ? true : parsed\n    }\n\n    get remaining ():number {\n        return this.max - this.count\n    }\n\n    get progress ():number {\n        // Returns 0-1, capped at 1 for over-limit\n        return Math.min(this.count / this.max, 1)\n    }\n\n    get isOverLimit ():boolean {\n        return this.count > this.max\n    }\n\n    get isNearLimit ():boolean {\n        // If warn is a number, use that as the threshold\n        // Otherwise default to 20 characters remaining\n        const threshold = typeof this.warn === 'number' ? this.warn : 20\n        return this.remaining <= threshold\n    }\n\n    get shouldShowCount ():boolean {\n        // If hide-count is present, never show\n        if (this.hideCount) return false\n\n        // If warn is present (including 0), only show when near limit\n        if (this.warn !== false) return this.isNearLimit\n\n        // Otherwise, always show\n        return true\n    }\n\n    attributeChangedCallback (name:string, oldValue:string, newValue:string) {\n        debug('attribute changed', name, oldValue, newValue)\n        if (this.isConnected) {\n            this.render()\n        }\n    }\n\n    disconnectedCallback () {\n        debug('disconnected')\n    }\n\n    connectedCallback () {\n        this.render()\n    }\n\n    render () {\n        // Set data attribute for over-limit state\n        if (this.isOverLimit) {\n            this.setAttribute('data-over-limit', '')\n        } else {\n            this.removeAttribute('data-over-limit')\n        }\n\n        // Set visibility attribute for count\n        if (this.shouldShowCount) {\n            this.removeAttribute('data-hide-count')\n        } else {\n            this.setAttribute('data-hide-count', '')\n        }\n\n        // First render the HTML structure\n        this.innerHTML = `\n            <div class=\"counter-wrapper\">\n                <span class=\"remaining\">${this.remaining}</span>\n                <svg class=\"circle-container\" viewBox=\"0 0 100 100\" aria-hidden=\"true\">\n                    <circle class=\"track\" cx=\"50\" cy=\"50\" r=\"47.5\" />\n                    <circle class=\"progress\" cx=\"50\" cy=\"50\" r=\"47.5\" />\n                </svg>\n            </div>\n        `\n\n        // Now get the actual rendered size in pixels\n        const svg = this.querySelector('.circle-container') as SVGElement\n        if (svg) {\n            const rect = svg.getBoundingClientRect()\n            const size = rect.width || 24\n            const computedStyle = getComputedStyle(this)\n            const strokeWidth = parseFloat(computedStyle.getPropertyValue('--counter-stroke-width')) || 3\n            const radius = (size - strokeWidth) / 2\n            const circumference = 2 * Math.PI * radius\n            const offset = circumference - (this.progress * circumference)\n\n            // Set CSS custom properties for dynamic values\n            this.style.setProperty('--circumference', String(circumference))\n            this.style.setProperty('--offset', String(offset))\n\n            // Update SVG viewBox to match the actual pixel size\n            svg.setAttribute('viewBox', `0 0 ${size} ${size}`)\n            const circles = svg.querySelectorAll('circle')\n            circles.forEach(circle => {\n                circle.setAttribute('cx', String(size / 2))\n                circle.setAttribute('cy', String(size / 2))\n                circle.setAttribute('r', String(radius))\n            })\n        }\n\n        // Update aria-label for screen readers\n        this.setAttribute('role', 'status')\n        this.setAttribute('aria-live', 'polite')\n        this.setAttribute('aria-label', this.isOverLimit ?\n            `${Math.abs(this.remaining)} characters over limit` :\n            `${this.remaining} characters remaining`\n        )\n    }\n}\n\ndefine(CharacterCounter.TAG, CharacterCounter)\n"],
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAAuB;AACvB,mBAAkB;AAClB,MAAM,YAAQ,aAAAA,SAAM,mBAAmB;AAyChC,MAAM,yBAAyB,YAAY;AAAA,EA3ClD,OA2CkD;AAAA;AAAA;AAAA,EAC9C,OAAO,qBAAqB,CAAC,OAAO,SAAS,cAAc,MAAM;AAAA,EACjE,OAAO,MAAM;AAAA,EAEb,IAAI,MAAc;AACd,WAAO,SAAS,KAAK,aAAa,KAAK,KAAK,OAAO,EAAE;AAAA,EACzD;AAAA,EAEA,IAAI,QAAgB;AAChB,WAAO,SAAS,KAAK,aAAa,OAAO,KAAK,KAAK,EAAE;AAAA,EACzD;AAAA,EAEA,IAAI,MAAO,GAAG;AACV,SAAK,aAAa,SAAS,KAAK,CAAC;AAAA,EACrC;AAAA,EAEA,IAAI,YAAqB;AACrB,WAAO,KAAK,aAAa,YAAY;AAAA,EACzC;AAAA,EAEA,IAAI,OAAyB;AACzB,UAAM,QAAQ,KAAK,aAAa,MAAM;AACtC,QAAI,UAAU,KAAM,QAAO;AAC3B,QAAI,UAAU,GAAI,QAAO;AACzB,UAAM,SAAS,SAAS,OAAO,EAAE;AACjC,WAAO,MAAM,MAAM,IAAI,OAAO;AAAA,EAClC;AAAA,EAEA,IAAI,YAAoB;AACpB,WAAO,KAAK,MAAM,KAAK;AAAA,EAC3B;AAAA,EAEA,IAAI,WAAmB;AAEnB,WAAO,KAAK,IAAI,KAAK,QAAQ,KAAK,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEA,IAAI,cAAuB;AACvB,WAAO,KAAK,QAAQ,KAAK;AAAA,EAC7B;AAAA,EAEA,IAAI,cAAuB;AAGvB,UAAM,YAAY,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AAC9D,WAAO,KAAK,aAAa;AAAA,EAC7B;AAAA,EAEA,IAAI,kBAA2B;AAE3B,QAAI,KAAK,UAAW,QAAO;AAG3B,QAAI,KAAK,SAAS,MAAO,QAAO,KAAK;AAGrC,WAAO;AAAA,EACX;AAAA,EAEA,yBAA0B,MAAa,UAAiB,UAAiB;AACrE,UAAM,qBAAqB,MAAM,UAAU,QAAQ;AACnD,QAAI,KAAK,aAAa;AAClB,WAAK,OAAO;AAAA,IAChB;AAAA,EACJ;AAAA,EAEA,uBAAwB;AACpB,UAAM,cAAc;AAAA,EACxB;AAAA,EAEA,oBAAqB;AACjB,SAAK,OAAO;AAAA,EAChB;AAAA,EAEA,SAAU;AAEN,QAAI,KAAK,aAAa;AAClB,WAAK,aAAa,mBAAmB,EAAE;AAAA,IAC3C,OAAO;AACH,WAAK,gBAAgB,iBAAiB;AAAA,IAC1C;AAGA,QAAI,KAAK,iBAAiB;AACtB,WAAK,gBAAgB,iBAAiB;AAAA,IAC1C,OAAO;AACH,WAAK,aAAa,mBAAmB,EAAE;AAAA,IAC3C;AAGA,SAAK,YAAY;AAAA;AAAA,0CAEiB,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAShD,UAAM,MAAM,KAAK,cAAc,mBAAmB;AAClD,QAAI,KAAK;AACL,YAAM,OAAO,IAAI,sBAAsB;AACvC,YAAM,OAAO,KAAK,SAAS;AAC3B,YAAM,gBAAgB,iBAAiB,IAAI;AAC3C,YAAM,cAAc,WAAW,cAAc,iBAAiB,wBAAwB,CAAC,KAAK;AAC5F,YAAM,UAAU,OAAO,eAAe;AACtC,YAAM,gBAAgB,IAAI,KAAK,KAAK;AACpC,YAAM,SAAS,gBAAiB,KAAK,WAAW;AAGhD,WAAK,MAAM,YAAY,mBAAmB,OAAO,aAAa,CAAC;AAC/D,WAAK,MAAM,YAAY,YAAY,OAAO,MAAM,CAAC;AAGjD,UAAI,aAAa,WAAW,OAAO,IAAI,IAAI,IAAI,EAAE;AACjD,YAAM,UAAU,IAAI,iBAAiB,QAAQ;AAC7C,cAAQ,QAAQ,YAAU;AACtB,eAAO,aAAa,MAAM,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAO,aAAa,MAAM,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAO,aAAa,KAAK,OAAO,MAAM,CAAC;AAAA,MAC3C,CAAC;AAAA,IACL;AAGA,SAAK,aAAa,QAAQ,QAAQ;AAClC,SAAK,aAAa,aAAa,QAAQ;AACvC,SAAK;AAAA,MAAa;AAAA,MAAc,KAAK,cACjC,GAAG,KAAK,IAAI,KAAK,SAAS,CAAC,2BAC3B,GAAG,KAAK,SAAS;AAAA,IACrB;AAAA,EACJ;AACJ;AAAA,IAEA,6BAAO,iBAAiB,KAAK,gBAAgB;",
  "names": ["Debug"]
}
