{"version":3,"file":"chip.cjs","names":[],"sources":["../src/feedback/chip/chip.ts"],"sourcesContent":["import { bind, define, html, prop, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport type { ComponentSize, RoundedSize, ThemeColor, VisualVariant } from '../../types';\n\nimport '../../content/icon/icon';\nimport {\n  colorThemeMixin,\n  disabledStateMixin,\n  forcedColorsMixin,\n  roundedVariantMixin,\n  sizeVariantMixin,\n} from '../../styles';\n// ============================================\n// Styles\n// ============================================\nimport componentStyles from './chip.css?inline';\n\n// ============================================\n// Types\n// ============================================\n\n/** Chip component properties */\ntype ChipBaseProps = {\n  /** Theme color */\n  color?: ThemeColor;\n  /** Disable interactions */\n  disabled?: boolean;\n  /** Accessible label (required for icon-only chips) */\n  label?: string;\n  /** Border radius override */\n  rounded?: RoundedSize | '';\n  /** Component size */\n  size?: ComponentSize;\n  /** Value associated with this chip — included in emitted event detail */\n  value?: string;\n  /** Visual style variant */\n  variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\ntype OreChipMode = 'static' | 'removable' | 'selectable' | 'action';\n\n/** Read-only presentation chip */\ntype StaticChipProps = {\n  mode?: Extract<OreChipMode, 'static'>;\n};\n\n/** Removable chip mode */\ntype RemovableChipProps = {\n  mode: Extract<OreChipMode, 'removable'>;\n};\n\n/** Selectable chip mode */\ntype SelectableChipProps = {\n  /** Controlled checked state for `mode=\"selectable\"` */\n  checked?: boolean | undefined;\n  /** Initial checked state for uncontrolled `mode=\"selectable\"` */\n  'default-checked'?: boolean;\n  mode: Extract<OreChipMode, 'selectable'>;\n};\n\n/** Action chip mode — behaves like a button, fires a click event without maintaining state */\ntype ActionChipProps = {\n  mode: Extract<OreChipMode, 'action'>;\n};\n\ntype OreChipComponentProps = ChipBaseProps & {\n  checked?: boolean | undefined;\n  'default-checked'?: boolean;\n  mode?: OreChipMode;\n};\n\nexport type OreChipEvents = {\n  change: { checked: boolean; originalEvent: Event; value: string | undefined };\n  click: { originalEvent: MouseEvent; value: string | undefined };\n  remove: { originalEvent: MouseEvent; value: string | undefined };\n};\n\nexport type OreChipProps = ChipBaseProps &\n  (StaticChipProps | RemovableChipProps | SelectableChipProps | ActionChipProps);\n\n/**\n * A compact, styled label element. Supports icons, a remove button, colors, sizes, and variants.\n * Commonly used to represent tags, filters, or selected options in a multiselect field.\n *\n * @element ore-chip\n *\n * @attr {string}  label     - Accessible label (required for icon-only chips)\n * @attr {string}  color     - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string}  variant   - Visual variant: 'solid' | 'flat' | 'bordered' | 'outline' | 'ghost'\n * @attr {string}  size      - Component size: 'sm' | 'md' | 'lg'\n * @attr {string}  rounded   - Border radius: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n * @attr {string}  mode      - Interaction mode: 'static' | 'removable' | 'selectable' | 'action'\n * @attr {boolean} disabled  - Disable the chip\n * @attr {string}  value     - Value included in emitted event detail\n * @attr {boolean} checked   - Controlled checked state for selectable chips\n * @attr {boolean} default-checked - Initial checked state for uncontrolled selectable chips\n *\n * @fires remove - Fired when the remove button is clicked. detail: { value: string, originalEvent: MouseEvent }\n * @fires change - Fired when a selectable chip toggles. detail: { checked: boolean, value: string, originalEvent: Event }\n * @fires click  - Fired when an action chip is clicked. detail: { value: string, originalEvent: MouseEvent }\n *\n * @slot         - Chip label text\n * @slot icon    - Leading icon or decoration\n *\n * @cssprop --chip-bg              - Background color\n * @cssprop --chip-color           - Text color\n * @cssprop --chip-border-color    - Border color\n * @cssprop --chip-radius          - Border radius\n * @cssprop --chip-font-size       - Font size\n * @cssprop --chip-font-weight     - Font weight\n * @cssprop --chip-padding-x       - Horizontal padding\n * @cssprop --chip-padding-y       - Vertical padding\n * @cssprop --chip-gap             - Gap between icon, label and remove button\n * @cssprop --chip-hover-bg        - Background on hover (interactive modes)\n * @cssprop --chip-hover-color     - Text color on hover (interactive modes)\n * @cssprop --chip-hover-border-color - Border color on hover (interactive modes)\n * @cssprop --chip-active-bg       - Background when pressed (interactive modes)\n * @cssprop --chip-active-color    - Text color when pressed (interactive modes)\n * @cssprop --chip-remove-bg       - Remove button background (bordered/outline variants)\n * @cssprop --chip-remove-color    - Remove button icon color (bordered/outline variants)\n * @cssprop --chip-remove-hover-bg - Remove button background on hover\n *\n * @part remove-btn - Remove action button.\n * @part chip-btn - Shadow part for the `chip-btn` element.\n * @part chip - Shadow part for the `chip` element.\n * @example\n * ```html\n * <!-- Static chip (read-only) -->\n * <ore-chip color=\"primary\">Design</ore-chip>\n *\n * <!-- Removable chip -->\n * <ore-chip color=\"success\" variant=\"flat\" mode=\"removable\" value=\"ts\">\n *   TypeScript\n * </ore-chip>\n *\n * <!-- Selectable chip (controlled) -->\n * <ore-chip color=\"info\" variant=\"flat\" mode=\"selectable\" checked value=\"ui\">\n *   UI\n * </ore-chip>\n *\n * <!-- Selectable chip (uncontrolled) -->\n * <ore-chip color=\"info\" variant=\"flat\" mode=\"selectable\" default-checked value=\"ui\">\n *   UI\n * </ore-chip>\n *\n * <!-- Action chip (acts like a button) -->\n * <ore-chip color=\"warning\" mode=\"action\" value=\"add\">\n *   <svg slot=\"icon\" ...></svg>\n *   Add Item\n * </ore-chip>\n *\n * <!-- Icon-only chip -->\n * <ore-chip color=\"error\" mode=\"action\" label=\"Delete\">\n *   <svg slot=\"icon\" ...></svg>\n * </ore-chip>\n * ```\n */\nexport const CHIP_TAG = 'ore-chip' as const;\ndefine<OreChipComponentProps>(CHIP_TAG, {\n  props: {\n    checked: {\n      default: undefined as OreChipComponentProps['checked'],\n      parse: (value: string | null) => (value == null ? undefined : value !== 'false'),\n      reflect: false,\n    },\n    color: prop.string<ThemeColor>(),\n    'default-checked': prop.bool(false),\n    disabled: prop.bool(false),\n    label: prop.string(),\n    mode: prop.oneOf(['static', 'removable', 'selectable', 'action'] as const, 'static'),\n    rounded: prop.string<RoundedSize | ''>(),\n    size: prop.string<ComponentSize>(),\n    value: prop.string(),\n    variant: prop.string<Exclude<VisualVariant, 'text' | 'frost'>>(),\n  },\n\n  setup(props) {\n    const emit = useEmit<OreChipEvents>();\n\n    // ============================================\n    // State Management\n    // ============================================\n    // Once a checked prop is provided, treat the chip as controlled for the rest of its lifecycle.\n    const isControlled = signal(props.checked.value !== undefined);\n    // Internal tracking for uncontrolled selectable chips; seeded from default-checked.\n    const checkedState = signal(!isControlled.value && props['default-checked'].value);\n\n    watch(props.checked, (value) => {\n      if (value !== undefined) {\n        isControlled.value = true;\n      }\n    });\n\n    // Effective checked value — reactive to checked prop changes in controlled mode.\n    const isChecked = computed(() => {\n      if (props.mode.value !== 'selectable') return false;\n\n      if (isControlled.value) {\n        return props.checked.value ?? false;\n      }\n\n      return checkedState.value;\n    });\n\n    bind({\n      attr: {\n        checked: () => (props.mode.value === 'selectable' && isChecked.value ? true : undefined),\n      },\n    });\n    // ============================================\n    // Event Handlers\n    // ============================================\n    function handleRemove(e: MouseEvent) {\n      if (props.disabled.value) return;\n\n      emit('remove', { originalEvent: e, value: props.value.value });\n    }\n\n    function handleSelectableActivate(e: MouseEvent) {\n      e.stopPropagation();\n\n      if (props.disabled.value) return;\n\n      const nextChecked = !isChecked.value;\n\n      if (!isControlled.value) {\n        checkedState.value = nextChecked;\n      }\n\n      emit('change', { checked: nextChecked, originalEvent: e, value: props.value.value });\n    }\n\n    function handleActionClick(e: MouseEvent) {\n      if (props.disabled.value) return;\n\n      emit('click', { originalEvent: e, value: props.value.value });\n    }\n\n    // ============================================\n    // Template Helpers\n    // ============================================\n    const renderChipContent = () => html`\n      <slot name=\"icon\"></slot>\n      <span class=\"label\"><slot></slot></span>\n    `;\n\n    const removeBtnLabel = () => {\n      const label = props.label.value || props.value.value;\n\n      return label ? `Remove ${label}` : 'Remove';\n    };\n\n    const renderRemoveButton = () => html`\n      <button\n        class=\"remove-btn\"\n        part=\"remove-btn\"\n        type=\"button\"\n        aria-label=\"${removeBtnLabel}\"\n        ?hidden=\"${() => props.mode.value !== 'removable'}\"\n        disabled=\"${props.disabled}\"\n        @click=\"${handleRemove}\">\n        <ore-icon name=\"x\" size=\"12\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n      </button>\n    `;\n\n    const renderSelectableChip = () => html`\n      <button\n        class=\"chip-btn\"\n        part=\"chip-btn\"\n        type=\"button\"\n        role=\"checkbox\"\n        aria-checked=\"${() => String(isChecked.value)}\"\n        aria-label=\"${props.label}\"\n        disabled=\"${props.disabled}\"\n        @click=\"${handleSelectableActivate}\">\n        <span class=\"chip\" part=\"chip\">${renderChipContent()}</span>\n      </button>\n    `;\n\n    const renderActionChip = () => html`\n      <button\n        class=\"chip-btn\"\n        part=\"chip-btn\"\n        type=\"button\"\n        aria-label=\"${props.label}\"\n        disabled=\"${props.disabled}\"\n        @click=\"${handleActionClick}\">\n        <span class=\"chip\" part=\"chip\">${renderChipContent()}</span>\n      </button>\n    `;\n\n    const renderStaticChip = () => html`\n      <span class=\"chip\" part=\"chip\">${renderChipContent()}</span>\n    `;\n\n    const renderRemovableChip = () => html`\n      <span class=\"chip\" part=\"chip\">${renderChipContent()} ${renderRemoveButton()}</span>\n    `;\n\n    // ============================================\n    // Render\n    // ============================================\n    return html`\n      ${() => {\n        const mode = props.mode.value;\n\n        if (mode === 'selectable') return renderSelectableChip();\n\n        if (mode === 'action') return renderActionChip();\n\n        if (mode === 'removable') return renderRemovableChip();\n\n        return renderStaticChip();\n      }}\n    `;\n  },\n  styles: [\n    colorThemeMixin,\n    disabledStateMixin,\n    roundedVariantMixin,\n    sizeVariantMixin({\n      lg: {\n        '--_font-size': 'var(--text-sm)',\n        '--_gap': 'var(--size-1-5)',\n        '--_padding-x': 'var(--size-3)',\n        '--_padding-y': 'var(--size-1)',\n      },\n      sm: {\n        '--_font-size': 'var(--text-xs)',\n        '--_gap': 'var(--size-0-5)',\n        '--_padding-x': 'var(--size-2-5)',\n        '--_padding-y': 'var(--size-px)',\n      },\n    }),\n    forcedColorsMixin,\n    componentStyles,\n  ],\n});\n"],"mappings":"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"}