<script setup>
import { computed, ref, inject } from "vue";
import { useNamespace } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import { radioGroupContextKey } from "./radio";
defineOptions({
  name: "YhRadioButton"
});
const props = defineProps({
  modelValue: { type: [String, Number, Boolean], required: false },
  value: { type: [String, Number, Boolean], required: false },
  name: { type: String, required: false },
  label: { type: String, required: false },
  size: { type: null, required: false },
  disabled: { type: Boolean, required: false, default: false },
  id: { type: String, required: false },
  tabindex: { type: [String, Number], required: false },
  themeOverrides: { type: null, required: false }
});
const emit = defineEmits(["update:modelValue", "change"]);
const ns = useNamespace("radio-button");
const radioGroup = inject(radioGroupContextKey, void 0);
const { themeStyle } = useComponentTheme(
  "radio-button",
  computed(() => props.themeOverrides || radioGroup?.themeOverrides)
);
const inputRef = ref();
const focused = ref(false);
const isGroup = computed(() => !!radioGroup);
const buttonSize = computed(() => {
  return props.size || radioGroup?.size || "default";
});
const isDisabled = computed(() => {
  return props.disabled || radioGroup?.disabled || false;
});
const radioName = computed(() => {
  return props.name || radioGroup?.name || "";
});
const isChecked = computed(() => {
  const value = props.value ?? props.label;
  if (isGroup.value && radioGroup) {
    return radioGroup.modelValue === value;
  }
  return props.modelValue === value;
});
const activeStyle = computed(() => {
  if (!isChecked.value) return {};
  const style = {};
  if (radioGroup?.fill) {
    style["--yh-radio-button-checked-bg-color"] = radioGroup.fill;
    style["--yh-radio-button-checked-border-color"] = radioGroup.fill;
  }
  if (radioGroup?.textColor) {
    style["--yh-radio-button-checked-text-color"] = radioGroup.textColor;
  }
  return style;
});
const buttonClasses = computed(() => [
  ns.b(),
  buttonSize.value !== "default" ? ns.m(buttonSize.value) : "",
  ns.is("disabled", isDisabled.value),
  ns.is("checked", isChecked.value),
  ns.is("focused", focused.value)
]);
const handleChange = () => {
  if (isDisabled.value) return;
  const value = props.value ?? props.label;
  if (isGroup.value && radioGroup) {
    radioGroup.changeEvent?.(value);
  } else {
    emit("update:modelValue", value);
    emit("change", value);
  }
};
const handleFocus = () => {
  focused.value = true;
};
const handleBlur = () => {
  focused.value = false;
};
const focus = () => {
  inputRef.value?.focus();
};
const blur = () => {
  inputRef.value?.blur();
};
defineExpose({
  ref: inputRef.value,
  focus,
  blur
});
</script>

<template>
  <label :class="buttonClasses" :style="[activeStyle, themeStyle]">
    <input
      ref="inputRef"
      :class="ns.e('original')"
      type="radio"
      :name="radioName"
      :id="id"
      :tabindex="tabindex"
      :disabled="isDisabled"
      :checked="isChecked"
      :value="value ?? label"
      @change="handleChange"
      @focus="handleFocus"
      @blur="handleBlur"
    />
    <span :class="ns.e('inner')">
      <slot>{{ label }}</slot>
    </span>
  </label>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-radio-button {
  --yh-radio-button-font-size: var(--yh-font-size-base);
  --yh-radio-button-text-color: var(--yh-text-color-regular);
  --yh-radio-button-bg-color: var(--yh-fill-color-blank);
  --yh-radio-button-border-color: var(--yh-border-color);
  --yh-radio-button-hover-text-color: var(--yh-color-primary);
  --yh-radio-button-checked-bg-color: var(--yh-color-primary);
  --yh-radio-button-checked-border-color: var(--yh-color-primary);
  --yh-radio-button-checked-text-color: var(--yh-color-primary-text, #ffffff);
  --yh-radio-button-disabled-bg-color: var(--yh-fill-color-light);
  --yh-radio-button-disabled-border-color: var(--yh-border-color-light);
  --yh-radio-button-disabled-text-color: var(--yh-text-color-placeholder);
  position: relative;
  display: inline-flex;
  outline: none;
  margin: 0;
  padding: 0;
  cursor: pointer;
}
.yh-radio-button__original {
  position: absolute;
  z-index: -1;
  width: 0;
  height: 0;
  margin: 0;
  opacity: 0;
  outline: none;
}

.yh-radio-button__inner {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--yh-component-size-default);
  padding: 0 16px;
  font-size: var(--yh-radio-button-font-size);
  font-weight: var(--yh-font-weight-normal);
  color: var(--yh-radio-button-text-color);
  background-color: var(--yh-radio-button-bg-color);
  border: var(--yh-border-width) var(--yh-border-style) var(--yh-radio-button-border-color);
  line-height: 1;
  white-space: nowrap;
  transition: var(--yh-transition-fast);
  box-sizing: border-box;
  border-radius: 0;
}

.yh-radio-button:first-child .yh-radio-button__inner {
  border-radius: var(--yh-radius-base) 0 0 var(--yh-radius-base);
}
.yh-radio-button:not(:first-child) .yh-radio-button__inner {
  margin-left: -1px;
}
.yh-radio-button:last-child .yh-radio-button__inner {
  border-radius: 0 var(--yh-radius-base) var(--yh-radius-base) 0;
}
.yh-radio-button:first-child:last-child .yh-radio-button__inner {
  border-radius: var(--yh-radius-base);
}
.yh-radio-button:hover:not(.is-disabled) .yh-radio-button__inner:not(.is-checked) {
  color: var(--yh-radio-button-hover-text-color);
}

.yh-radio-button.is-checked {
  z-index: 1;
}
.yh-radio-button.is-checked .yh-radio-button__inner {
  color: var(--yh-radio-button-checked-text-color) !important;
  background-color: var(--yh-radio-button-checked-bg-color);
  border-color: var(--yh-radio-button-checked-border-color);
}

.yh-radio-button.is-focused .yh-radio-button__inner {
  box-shadow: 0 0 0 2px var(--yh-color-primary-light-7);
}

.yh-radio-button.is-disabled {
  cursor: not-allowed;
}
.yh-radio-button.is-disabled .yh-radio-button__inner {
  color: var(--yh-radio-button-disabled-text-color);
  background-color: var(--yh-radio-button-disabled-bg-color);
  border-color: var(--yh-radio-button-disabled-border-color);
  cursor: not-allowed;
}

.yh-radio-button.is-disabled.is-checked .yh-radio-button__inner {
  background-color: var(--yh-border-color-light);
  border-color: var(--yh-border-color-light);
}

.yh-radio-button--large {
  --yh-radio-button-font-size: var(--yh-font-size-md);
}
.yh-radio-button--large .yh-radio-button__inner {
  height: var(--yh-component-size-large);
  padding: 0 20px;
}

.yh-radio-button--large:first-child .yh-radio-button__inner {
  border-radius: var(--yh-radius-md) 0 0 var(--yh-radius-md);
}
.yh-radio-button--large:last-child .yh-radio-button__inner {
  border-radius: 0 var(--yh-radius-md) var(--yh-radius-md) 0;
}
.yh-radio-button--large:first-child:last-child .yh-radio-button__inner {
  border-radius: var(--yh-radius-md);
}

.yh-radio-button--small {
  --yh-radio-button-font-size: var(--yh-font-size-xs);
}
.yh-radio-button--small .yh-radio-button__inner {
  height: var(--yh-component-size-small);
  padding: 0 12px;
}

.yh-radio-button--small:first-child .yh-radio-button__inner {
  border-radius: var(--yh-radius-sm) 0 0 var(--yh-radius-sm);
}
.yh-radio-button--small:last-child .yh-radio-button__inner {
  border-radius: 0 var(--yh-radius-sm) var(--yh-radius-sm) 0;
}
.yh-radio-button--small:first-child:last-child .yh-radio-button__inner {
  border-radius: var(--yh-radius-sm);
}
</style>
