{"version":3,"file":"BqAvatar-B-XVTGci.cjs","names":[],"sources":["../src/components/avatar/BqAvatar.ts"],"sourcesContent":["/**\r\n * Avatar component - user/entity image or initials.\r\n * @element bq-avatar\r\n * @prop {string} src    - Image URL\r\n * @prop {string} alt    - Alt text / initials source\r\n * @prop {string} size   - xs | sm | md | lg | xl\r\n * @prop {string} shape  - circle | square\r\n * @prop {string} status - online | away | busy | offline | \"\"\r\n * @slot - Custom content\r\n */\r\nimport type { ComponentDefinition } from '@bquery/bquery/component';\r\nimport { component, html } from '@bquery/bquery/component';\r\nimport { escapeHtml } from '@bquery/bquery/security';\r\nimport { getBaseStyles } from '../../utils/styles.js';\r\n\r\ntype BqAvatarProps = {\r\n  src: string;\r\n  alt: string;\r\n  size: string;\r\n  shape: string;\r\n  status: string;\r\n};\r\n\r\ntype GraphemeSegment = { segment: string };\r\ntype GraphemeSegmenter = {\r\n  segment(input: string): Iterable<GraphemeSegment>;\r\n};\r\n\r\nfunction getGraphemes(value: string): string[] {\r\n  if (!value) return [];\r\n\r\n  const intlWithSegmenter = Intl as typeof Intl & {\r\n    Segmenter?: new (\r\n      locales?: string | string[],\r\n      options?: { granularity: 'grapheme' }\r\n    ) => GraphemeSegmenter;\r\n  };\r\n\r\n  if (intlWithSegmenter.Segmenter) {\r\n    const segmenter = new intlWithSegmenter.Segmenter(undefined, {\r\n      granularity: 'grapheme',\r\n    });\r\n    return Array.from(segmenter.segment(value), (part) => part.segment);\r\n  }\r\n\r\n  return Array.from(value);\r\n}\r\n\r\nfunction getInitials(alt: string): string {\r\n  const words = alt.trim().split(/\\s+/).filter(Boolean);\r\n  if (!words.length || !words[0]) return '?';\r\n\r\n  if (words.length === 1) {\r\n    const word = words[0];\r\n    const graphemes = getGraphemes(word);\r\n    if (!graphemes.length) return '?';\r\n\r\n    const isLatinLike = /[\\p{Script=Latin}\\p{Number}]/u.test(word);\r\n    const initials = isLatinLike\r\n      ? (graphemes[0] ?? '')\r\n      : graphemes.slice(0, 2).join('');\r\n    return initials ? initials.toLocaleUpperCase() : '?';\r\n  }\r\n\r\n  const firstWord = words[0] ?? '';\r\n  const lastWord = words[words.length - 1] ?? firstWord;\r\n  const first = getGraphemes(firstWord)[0] ?? '';\r\n  const last = getGraphemes(lastWord)[0] ?? '';\r\n  return `${first}${last}`.toLocaleUpperCase();\r\n}\r\n\r\nconst definition: ComponentDefinition<BqAvatarProps> = {\r\n  props: {\r\n    src: { type: String, default: '' },\r\n    alt: { type: String, default: '' },\r\n    size: { type: String, default: 'md' },\r\n    shape: { type: String, default: 'circle' },\r\n    status: { type: String, default: '' },\r\n  },\r\n  styles: `\r\n    ${getBaseStyles()}\r\n    :host { display: inline-block; position: relative; }\r\n    .avatar {\r\n      overflow: hidden; display: flex; align-items: center; justify-content: center;\r\n      background: var(--bq-color-primary-100,#dbeafe); color: var(--bq-color-primary-700,#1d4ed8);\r\n      font-weight: var(--bq-font-weight-semibold,600); font-family: var(--bq-font-family-sans);\r\n      user-select: none; flex-shrink: 0;\r\n    }\r\n    .avatar[data-shape=\"circle\"] { border-radius: var(--bq-radius-full,9999px); }\r\n    .avatar[data-shape=\"square\"] { border-radius: var(--bq-radius-lg,0.5rem); }\r\n    .avatar[data-size=\"xs\"]  { width: 1.5rem; height: 1.5rem; font-size: 0.5625rem; }\r\n    .avatar[data-size=\"sm\"]  { width: 2rem;   height: 2rem;   font-size: 0.75rem; }\r\n    .avatar[data-size=\"md\"]  { width: 2.5rem; height: 2.5rem; font-size: 0.9375rem; }\r\n    .avatar[data-size=\"lg\"]  { width: 3rem;   height: 3rem;   font-size: 1.125rem; }\r\n    .avatar[data-size=\"xl\"]  { width: 4rem;   height: 4rem;   font-size: 1.5rem; }\r\n    .avatar img { width: 100%; height: 100%; object-fit: cover; }\r\n    .status {\r\n      position: absolute; bottom: 0; right: 0; border-radius: var(--bq-radius-full,9999px);\r\n      border: 2px solid var(--bq-bg-base,#fff);\r\n    }\r\n    :host([size=\"xs\"])  .status { width: 0.4rem;  height: 0.4rem; }\r\n    :host([size=\"sm\"])  .status { width: 0.5rem;  height: 0.5rem; }\r\n    :host([size=\"md\"])  .status { width: 0.7rem;  height: 0.7rem; }\r\n    :host([size=\"lg\"])  .status { width: 0.85rem; height: 0.85rem; }\r\n    :host([size=\"xl\"])  .status { width: 1.1rem;  height: 1.1rem; }\r\n    .status[data-status=\"online\"]  { background: #22c55e; }\r\n    .status[data-status=\"away\"]    { background: #f59e0b; }\r\n    .status[data-status=\"busy\"]    { background: #ef4444; }\r\n    .status[data-status=\"offline\"] { background: #94a3b8; }\r\n  `,\r\n  render({ props }) {\r\n    const content = props.src\r\n      ? `<img src=\"${escapeHtml(props.src)}\" alt=\"${escapeHtml(props.alt)}\" />`\r\n      : `<slot>${escapeHtml(getInitials(props.alt))}</slot>`;\r\n    const statusEl = props.status\r\n      ? `<span part=\"status\" class=\"status\" data-status=\"${escapeHtml(props.status)}\" role=\"img\" aria-label=\"${escapeHtml(props.status)}\"></span>`\r\n      : '';\r\n    return html`\r\n      <div\r\n        part=\"avatar\"\r\n        class=\"avatar\"\r\n        data-size=\"${escapeHtml(props.size)}\"\r\n        data-shape=\"${escapeHtml(props.shape)}\"\r\n        role=\"img\"\r\n        aria-label=\"${escapeHtml(props.alt)}\"\r\n      >\r\n        ${content}\r\n      </div>\r\n      ${statusEl}\r\n    `;\r\n  },\r\n};\r\n\r\ncomponent<BqAvatarProps>('bq-avatar', definition);\r\n"],"mappings":";;;;;AA4BA,SAAS,aAAa,OAAyB;AAC7C,KAAI,CAAC,MAAO,QAAO,EAAE;CAErB,MAAM,oBAAoB;AAO1B,KAAI,kBAAkB,WAAW;EAC/B,MAAM,YAAY,IAAI,kBAAkB,UAAU,KAAA,GAAW,EAC3D,aAAa,YACd,CAAC;AACF,SAAO,MAAM,KAAK,UAAU,QAAQ,MAAM,GAAG,SAAS,KAAK,QAAQ;;AAGrE,QAAO,MAAM,KAAK,MAAM;;AAG1B,SAAS,YAAY,KAAqB;CACxC,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,MAAM,CAAC,OAAO,QAAQ;AACrD,KAAI,CAAC,MAAM,UAAU,CAAC,MAAM,GAAI,QAAO;AAEvC,KAAI,MAAM,WAAW,GAAG;EACtB,MAAM,OAAO,MAAM;EACnB,MAAM,YAAY,aAAa,KAAK;AACpC,MAAI,CAAC,UAAU,OAAQ,QAAO;EAG9B,MAAM,WADc,gCAAgC,KAAK,KACxC,GACZ,UAAU,MAAM,KACjB,UAAU,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG;AAClC,SAAO,WAAW,SAAS,mBAAmB,GAAG;;CAGnD,MAAM,YAAY,MAAM,MAAM;CAC9B,MAAM,WAAW,MAAM,MAAM,SAAS,MAAM;AAG5C,QAAO,GAFO,aAAa,UAAU,CAAC,MAAM,KAC/B,aAAa,SAAS,CAAC,MAAM,KACjB,mBAAmB;;AAiE9C,2BAAA,EAAyB,aAAa;CA7DpC,OAAO;EACL,KAAK;GAAE,MAAM;GAAQ,SAAS;GAAI;EAClC,KAAK;GAAE,MAAM;GAAQ,SAAS;GAAI;EAClC,MAAM;GAAE,MAAM;GAAQ,SAAS;GAAM;EACrC,OAAO;GAAE,MAAM;GAAQ,SAAS;GAAU;EAC1C,QAAQ;GAAE,MAAM;GAAQ,SAAS;GAAI;EACtC;CACD,QAAQ;MACJ,eAAA,eAAe,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BpB,OAAO,EAAE,SAAS;EAChB,MAAM,UAAU,MAAM,MAClB,aAAa,2BAAA,GAAW,MAAM,IAAI,CAAC,SAAS,2BAAA,GAAW,MAAM,IAAI,CAAC,QAClE,SAAS,2BAAA,GAAW,YAAY,MAAM,IAAI,CAAC,CAAC;EAChD,MAAM,WAAW,MAAM,SACnB,mDAAmD,2BAAA,GAAW,MAAM,OAAO,CAAC,2BAA2B,2BAAA,GAAW,MAAM,OAAO,CAAC,aAChI;AACJ,SAAO,2BAAA,CAAI;;;;qBAIM,2BAAA,GAAW,MAAM,KAAK,CAAC;sBACtB,2BAAA,GAAW,MAAM,MAAM,CAAC;;sBAExB,2BAAA,GAAW,MAAM,IAAI,CAAC;;UAElC,QAAQ;;QAEV,SAAS;;;CAKqB,CAAW"}