{"version":3,"file":"BqTextarea--D2Op9xZ.cjs","names":[],"sources":["../src/components/textarea/BqTextarea.ts"],"sourcesContent":["/**\r\n * Textarea form field.\r\n * @element bq-textarea\r\n * @prop {string}  label\r\n * @prop {string}  value\r\n * @prop {string}  placeholder\r\n * @prop {string}  name\r\n * @prop {number}  rows\r\n * @prop {boolean} disabled\r\n * @prop {boolean} readonly\r\n * @prop {boolean} required\r\n * @prop {string}  error\r\n * @prop {string}  hint\r\n * @prop {string}  maxlength\r\n * @prop {boolean} show-counter - Show character counter when maxlength is set\r\n * @fires bq-input  - { value: string }\r\n * @fires bq-change - { value: string }\r\n * @fires bq-focus\r\n * @fires bq-blur\r\n */\r\nimport type { ComponentDefinition } from '@bquery/bquery/component';\r\nimport { bool, component, html } from '@bquery/bquery/component';\r\nimport { escapeHtml } from '@bquery/bquery/security';\r\nimport { t } from '../../i18n/index.js';\r\nimport { uniqueId } from '../../utils/dom.js';\r\nimport { createFormProxy, type FormProxy } from '../../utils/form.js';\r\nimport { getBaseStyles } from '../../utils/styles.js';\r\n\r\ntype BqTextareaProps = {\r\n  label: string;\r\n  value: string;\r\n  placeholder: string;\r\n  name: string;\r\n  rows: number;\r\n  disabled: boolean;\r\n  readonly: boolean;\r\n  required: boolean;\r\n  error: string;\r\n  hint: string;\r\n  maxlength: string;\r\n  'show-counter': boolean;\r\n};\r\ntype BqTextareaState = { uid: string };\r\n\r\nconst definition: ComponentDefinition<BqTextareaProps, BqTextareaState> = {\r\n  props: {\r\n    label: { type: String, default: '' },\r\n    value: { type: String, default: '' },\r\n    placeholder: { type: String, default: '' },\r\n    name: { type: String, default: '' },\r\n    rows: { type: Number, default: 4 },\r\n    disabled: { type: Boolean, default: false },\r\n    readonly: { type: Boolean, default: false },\r\n    required: { type: Boolean, default: false },\r\n    error: { type: String, default: '' },\r\n    hint: { type: String, default: '' },\r\n    maxlength: { type: String, default: '' },\r\n    'show-counter': { type: Boolean, default: false },\r\n  },\r\n  state: {\r\n    uid: '',\r\n  },\r\n  styles: `\r\n    ${getBaseStyles()}\r\n    *, *::before, *::after { box-sizing: border-box; }\r\n    :host { display: block; }\r\n    .field { display: flex; flex-direction: column; gap: 0.375rem; }\r\n    .label { font-size: var(--bq-font-size-sm,0.875rem); font-weight: var(--bq-font-weight-medium,500); color: var(--bq-text-base,#0f172a); font-family: var(--bq-font-family-sans); display: flex; align-items: center; gap: 0.25rem; }\r\n    .required-mark { color: var(--bq-color-danger-600,#dc2626); }\r\n    textarea {\r\n      display: block; width: 100%; border: 1.5px solid var(--bq-border-emphasis,#cbd5e1);\r\n      border-radius: var(--bq-radius-lg,0.5rem); background: var(--bq-bg-base,#fff);\r\n      color: var(--bq-text-base,#0f172a); font-family: var(--bq-font-family-sans);\r\n      font-size: var(--bq-font-size-md,1rem); padding: 0.5rem 0.875rem;\r\n      resize: vertical; outline: none;\r\n      transition: border-color var(--bq-duration-fast) var(--bq-easing-standard), box-shadow var(--bq-duration-fast) var(--bq-easing-standard);\r\n    }\r\n    textarea:focus { border-color: var(--bq-border-focus,#2563eb); box-shadow: var(--bq-focus-ring); }\r\n    :host([error]:not([error=\"\"])) textarea { border-color: var(--bq-color-danger-500,#ef4444); }\r\n    :host([error]:not([error=\"\"])) textarea:focus { border-color: var(--bq-color-danger-500,#ef4444); box-shadow: var(--bq-focus-ring-danger); }\r\n    :host([disabled]) textarea { opacity: 0.5; cursor: not-allowed; background: var(--bq-bg-muted,#f1f5f9); }\r\n    textarea::placeholder { color: var(--bq-text-subtle,#94a3b8); }\r\n    .hint { font-size: var(--bq-font-size-sm,0.875rem); color: var(--bq-text-muted,#475569); font-family: var(--bq-font-family-sans); }\r\n    .error-msg { font-size: var(--bq-font-size-sm,0.875rem); color: var(--bq-color-danger-600,#dc2626); font-family: var(--bq-font-family-sans); }\r\n    .footer { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }\r\n    .counter { font-size: var(--bq-font-size-sm,0.875rem); color: var(--bq-text-muted,#475569); font-family: var(--bq-font-family-sans); margin-left: auto; }\r\n    .counter[data-over=\"true\"] { color: var(--bq-color-danger-600,#dc2626); }\r\n    @media (prefers-reduced-motion: reduce) {\r\n      textarea { transition: none; }\r\n    }\r\n  `,\r\n  connected() {\r\n    type BQEl = HTMLElement & {\r\n      setState(k: 'uid', v: string): void;\r\n      getState<T>(k: string): T;\r\n    };\r\n    const self = this as unknown as BQEl;\r\n    if (!self.getState<string>('uid')) self.setState('uid', uniqueId('bq-ta'));\r\n\r\n    // Form proxy for native <form> participation\r\n    const name = self.getAttribute('name') ?? '';\r\n    const value = self.getAttribute('value') ?? '';\r\n    const disabled = self.hasAttribute('disabled');\r\n    const proxy = createFormProxy(self, name, value, disabled, {\r\n      getLiveValue: () => {\r\n        const ta = self.shadowRoot?.querySelector(\r\n          'textarea'\r\n        ) as HTMLTextAreaElement | null;\r\n        return ta ? ta.value : (self.getAttribute('value') ?? '');\r\n      },\r\n    });\r\n    (self as unknown as Record<string, unknown>)['_formProxy'] = proxy;\r\n\r\n    const ih = (e: Event) => {\r\n      const t = e.target as HTMLTextAreaElement | null;\r\n      if (t?.tagName === 'TEXTAREA') {\r\n        self.setAttribute('value', t.value);\r\n        proxy.setValue(t.value);\r\n        self.dispatchEvent(\r\n          new CustomEvent('bq-input', {\r\n            detail: { value: t.value },\r\n            bubbles: true,\r\n            composed: true,\r\n          })\r\n        );\r\n      }\r\n    };\r\n    const ch = (e: Event) => {\r\n      const t = e.target as HTMLTextAreaElement | null;\r\n      if (t?.tagName === 'TEXTAREA')\r\n        self.dispatchEvent(\r\n          new CustomEvent('bq-change', {\r\n            detail: { value: t.value },\r\n            bubbles: true,\r\n            composed: true,\r\n          })\r\n        );\r\n    };\r\n    const fh = (e: Event) => {\r\n      if ((e.target as Element)?.tagName === 'TEXTAREA')\r\n        self.dispatchEvent(\r\n          new CustomEvent('bq-focus', { bubbles: true, composed: true })\r\n        );\r\n    };\r\n    const bh = (e: Event) => {\r\n      if ((e.target as Element)?.tagName === 'TEXTAREA')\r\n        self.dispatchEvent(\r\n          new CustomEvent('bq-blur', { bubbles: true, composed: true })\r\n        );\r\n    };\r\n    const s = self as unknown as Record<string, unknown>;\r\n    s['_ih'] = ih;\r\n    s['_ch'] = ch;\r\n    s['_fh'] = fh;\r\n    s['_bh'] = bh;\r\n    self.shadowRoot?.addEventListener('input', ih);\r\n    self.shadowRoot?.addEventListener('change', ch);\r\n    self.shadowRoot?.addEventListener('focusin', fh);\r\n    self.shadowRoot?.addEventListener('focusout', bh);\r\n  },\r\n  disconnected() {\r\n    const s = this as unknown as Record<string, unknown>;\r\n    const sr = this.shadowRoot;\r\n    (['_ih', '_ch', '_fh', '_bh'] as const).forEach((k) => {\r\n      const h = s[k] as EventListener | undefined;\r\n      if (h)\r\n        sr?.removeEventListener(\r\n          k === '_ih'\r\n            ? 'input'\r\n            : k === '_ch'\r\n              ? 'change'\r\n              : k === '_fh'\r\n                ? 'focusin'\r\n                : 'focusout',\r\n          h\r\n        );\r\n    });\r\n    (s['_formProxy'] as FormProxy | undefined)?.cleanup();\r\n  },\r\n  updated() {\r\n    const s = this as unknown as Record<string, unknown>;\r\n    const proxy = s['_formProxy'] as FormProxy | undefined;\r\n    if (proxy) {\r\n      proxy.setName(this.getAttribute('name') ?? '');\r\n      proxy.setValue(this.getAttribute('value') ?? '');\r\n      proxy.setDisabled(this.hasAttribute('disabled'));\r\n    }\r\n  },\r\n  render({ props, state }) {\r\n    const hasError = Boolean(props.error);\r\n    const uid = state.uid || 'bq-ta';\r\n    const maxLen = props.maxlength ? parseInt(props.maxlength, 10) : 0;\r\n    const showCounter = props['show-counter'] && maxLen > 0;\r\n    const charCount = props.value.length;\r\n    const isOver = showCounter && charCount > maxLen;\r\n    const hasFooter = hasError || Boolean(props.hint) || showCounter;\r\n    const describedByParts: string[] = [];\r\n    if (hasError) describedByParts.push(`${uid}-err`);\r\n    else if (props.hint) describedByParts.push(`${uid}-hint`);\r\n    if (showCounter) describedByParts.push(`${uid}-counter`);\r\n    const describedBy = describedByParts.join(' ');\r\n    return html`\r\n      <div class=\"field\" part=\"field\">\r\n        ${props.label\r\n          ? `<label class=\"label\" for=\"${uid}\" part=\"label\">${escapeHtml(props.label)}${props.required ? '<span class=\"required-mark\" aria-hidden=\"true\"> *</span>' : ''}</label>`\r\n          : ''}\r\n        <textarea\r\n          part=\"textarea\"\r\n          id=\"${uid}\"\r\n          name=\"${escapeHtml(props.name)}\"\r\n          rows=\"${String(props.rows)}\"\r\n          placeholder=\"${escapeHtml(props.placeholder)}\"\r\n          ${props.maxlength ? `maxlength=\"${escapeHtml(props.maxlength)}\"` : ''}\r\n          ${bool('disabled', props.disabled)}\r\n          ${bool('readonly', props.readonly)}\r\n          ${bool('required', props.required)}\r\n          aria-invalid=\"${hasError ? 'true' : 'false'}\"\r\n          ${props.required ? 'aria-required=\"true\"' : ''}\r\n          ${describedBy ? `aria-describedby=\"${describedBy}\"` : ''}\r\n          ${hasError ? `aria-errormessage=\"${uid}-err\"` : ''}\r\n        >\r\n${escapeHtml(props.value)}</textarea\r\n        >\r\n        ${hasFooter\r\n          ? `<div class=\"footer\" part=\"footer\">\r\n              <span>\r\n                ${\r\n                  hasError\r\n                    ? `<span class=\"error-msg\" id=\"${uid}-err\" role=\"alert\" part=\"error\">${escapeHtml(props.error)}</span>`\r\n                    : ''\r\n                }\r\n                ${\r\n                  props.hint && !hasError\r\n                    ? `<span class=\"hint\" id=\"${uid}-hint\" part=\"hint\">${escapeHtml(props.hint)}</span>`\r\n                    : ''\r\n                }\r\n              </span>\r\n              ${\r\n                showCounter\r\n                  ? `<span class=\"counter\" id=\"${uid}-counter\" part=\"counter\" data-over=\"${isOver ? 'true' : 'false'}\" aria-live=\"polite\">${escapeHtml(\r\n                      t('input.characterCount', {\r\n                        count: charCount,\r\n                        max: maxLen,\r\n                      })\r\n                    )}</span>`\r\n                  : ''\r\n              }\r\n            </div>`\r\n          : ''}\r\n      </div>\r\n    `;\r\n  },\r\n};\r\n\r\ncomponent<BqTextareaProps, BqTextareaState>('bq-textarea', definition);\r\n"],"mappings":"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"}