<script setup>
import { computed, ref, inject, onMounted, watch } from "vue";
import { useNamespace, useConfig } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import { checkboxGroupContextKey } from "./checkbox";
defineOptions({
  name: "YhCheckbox"
});
const props = defineProps({
  modelValue: { type: [String, Number, Boolean], required: false },
  trueValue: { type: [String, Number, Boolean], required: false, default: true },
  falseValue: { type: [String, Number, Boolean], required: false, default: false },
  value: { type: [String, Number, Boolean], required: false },
  name: { type: String, required: false },
  label: { type: String, required: false },
  size: { type: null, required: false, default: "default" },
  disabled: { type: Boolean, required: false, default: false },
  indeterminate: { type: Boolean, required: false, default: false },
  border: { type: Boolean, required: false, default: false },
  validateEvent: { type: Boolean, required: false, default: true },
  id: { type: String, required: false },
  tabindex: { type: [String, Number], required: false },
  checked: { type: Boolean, required: false },
  themeOverrides: { type: null, required: false }
});
const emit = defineEmits(["update:modelValue", "change"]);
const ns = useNamespace("checkbox");
const checkboxGroup = inject(checkboxGroupContextKey, void 0);
const { themeStyle } = useComponentTheme(
  "checkbox",
  computed(() => props.themeOverrides || checkboxGroup?.themeOverrides)
);
const inputRef = ref();
const focused = ref(false);
const hovering = ref(false);
const { globalSize } = useConfig();
const isGroup = computed(() => !!checkboxGroup);
const checkboxSize = computed(() => {
  return (props.size !== "default" ? props.size : checkboxGroup?.size) || globalSize.value || "default";
});
const isDisabled = computed(() => {
  return props.disabled || checkboxGroup?.disabled || false;
});
const isLimitDisabled = computed(() => {
  if (isGroup.value && checkboxGroup) {
    const modelValue = checkboxGroup.modelValue || [];
    const isChecked2 = modelValue.includes(props.value);
    if (checkboxGroup.max !== void 0 && modelValue.length >= checkboxGroup.max && !isChecked2) {
      return true;
    }
    if (checkboxGroup.min !== void 0 && modelValue.length <= checkboxGroup.min && isChecked2) {
      return true;
    }
  }
  return false;
});
const actualDisabled = computed(() => isDisabled.value || isLimitDisabled.value);
const isChecked = computed(() => {
  if (isGroup.value && checkboxGroup) {
    return (checkboxGroup.modelValue || []).includes(props.value);
  }
  return props.modelValue === props.trueValue;
});
const checkboxClasses = computed(() => [
  ns.b(),
  ns.m(checkboxSize.value),
  ns.is("disabled", actualDisabled.value),
  ns.is("checked", isChecked.value),
  ns.is("indeterminate", props.indeterminate),
  ns.is("focused", focused.value),
  ns.is("border", props.border)
]);
const innerClasses = computed(() => [ns.e("inner")]);
const handleChange = (event) => {
  if (actualDisabled.value) return;
  const target = event.target;
  if (isGroup.value && checkboxGroup) {
    const currentValue = [...checkboxGroup.modelValue || []];
    const value = props.value;
    if (target.checked) {
      if (!currentValue.includes(value)) {
        currentValue.push(value);
      }
    } else {
      const index = currentValue.indexOf(value);
      if (index > -1) {
        currentValue.splice(index, 1);
      }
    }
    checkboxGroup.changeEvent?.(currentValue);
  } else {
    const newValue = target.checked ? props.trueValue : props.falseValue;
    emit("update:modelValue", newValue);
    emit("change", newValue);
  }
};
const handleFocus = () => {
  focused.value = true;
};
const handleBlur = () => {
  focused.value = false;
};
const focus = () => {
  inputRef.value?.focus();
};
const blur = () => {
  inputRef.value?.blur();
};
watch(
  () => props.checked,
  (val) => {
    if (val !== void 0 && !isGroup.value) {
      const newValue = val ? props.trueValue : props.falseValue;
      if (props.modelValue !== newValue) {
        emit("update:modelValue", newValue);
      }
    }
  },
  { immediate: true }
);
onMounted(() => {
  if (inputRef.value && props.checked !== void 0 && !isGroup.value) {
    inputRef.value.checked = isChecked.value;
  }
});
defineExpose({
  get ref() {
    return inputRef.value;
  },
  get checked() {
    return isChecked.value;
  },
  focus,
  blur
});
</script>

<template>
  <label
    :class="checkboxClasses"
    :style="themeStyle"
    @mouseenter="hovering = true"
    @mouseleave="hovering = false"
  >
    <span
      :class="[ns.e('input'), ns.is('disabled', actualDisabled), ns.is('checked', isChecked), ns.is('indeterminate', props.indeterminate)]"
    >
      <span :class="innerClasses"></span>
      <input
        ref="inputRef"
        :class="ns.e('original')"
        type="checkbox"
        :name="name"
        :id="id"
        :tabindex="tabindex"
        :disabled="actualDisabled"
        :checked="isChecked"
        @change="handleChange"
        @focus="handleFocus"
        @blur="handleBlur"
      />
    </span>
    <span v-if="$slots.default || label" :class="ns.e('label')">
      <slot>{{ label }}</slot>
    </span>
  </label>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-checkbox {
  --yh-checkbox-font-size: var(--yh-font-size-base);
  --yh-checkbox-font-weight: var(--yh-font-weight-medium);
  --yh-checkbox-text-color: var(--yh-text-color-regular);
  --yh-checkbox-input-height: 14px;
  --yh-checkbox-input-width: 14px;
  --yh-checkbox-border-radius: var(--yh-radius-sm);
  --yh-checkbox-bg-color: var(--yh-fill-color-blank);
  --yh-checkbox-input-border: 1px solid var(--yh-border-color);
  --yh-checkbox-input-border-color-hover: var(--yh-color-primary);
  --yh-checkbox-checked-bg-color: var(--yh-color-primary);
  --yh-checkbox-checked-icon-color: var(--yh-color-primary-text, var(--yh-color-white, #fff));
  --yh-checkbox-checked-text-color: var(--yh-color-primary);
  --yh-checkbox-disabled-input-fill: var(--yh-fill-color-light);
  --yh-checkbox-disabled-border-color: var(--yh-border-color);
  --yh-checkbox-disabled-icon-color: var(--yh-text-color-placeholder);
  --yh-checkbox-disabled-checked-input-fill: var(--yh-border-color);
  --yh-checkbox-disabled-checked-input-border-color: var(--yh-border-color);
  --yh-checkbox-disabled-checked-icon-color: #fff;
  color: var(--yh-checkbox-text-color);
  font-weight: var(--yh-checkbox-font-weight);
  font-size: var(--yh-checkbox-font-size);
  position: relative;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  user-select: none;
  margin-right: 30px;
  height: 32px;
}
.yh-checkbox.is-disabled {
  cursor: not-allowed;
}

.yh-checkbox__input {
  white-space: nowrap;
  cursor: pointer;
  outline: none;
  display: inline-flex;
  position: relative;
}

.yh-checkbox__inner {
  display: inline-block;
  position: relative;
  border: var(--yh-checkbox-input-border);
  border-radius: var(--yh-checkbox-border-radius);
  box-sizing: border-box;
  width: var(--yh-checkbox-input-width);
  height: var(--yh-checkbox-input-height);
  background-color: var(--yh-checkbox-bg-color);
  z-index: 1;
  transition: border-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46), background-color 0.25s cubic-bezier(0.71, -0.46, 0.29, 1.46);
}
.yh-checkbox__inner:hover {
  border-color: var(--yh-checkbox-input-border-color-hover);
}
.yh-checkbox__inner::after {
  box-sizing: content-box;
  content: "";
  border: 1px solid transparent;
  border-left: 0;
  border-top: 0;
  height: 7px;
  left: 4px;
  position: absolute;
  top: 1px;
  transform: rotate(45deg) scaleY(0);
  width: 3px;
  transition: transform 0.15s ease-in 0.05s;
  transform-origin: center;
}

.yh-checkbox__original {
  opacity: 0;
  outline: none;
  position: absolute;
  margin: 0;
  width: 0;
  height: 0;
  z-index: -1;
}

.yh-checkbox__label {
  display: inline-block;
  padding-left: 8px;
  line-height: 1;
  font-size: var(--yh-checkbox-font-size);
  color: var(--yh-checkbox-text-color);
}

.yh-checkbox--large {
  --yh-checkbox-input-height: 16px;
  --yh-checkbox-input-width: 16px;
  --yh-checkbox-font-size: var(--yh-font-size-md);
  height: 40px;
}
.yh-checkbox--large .yh-checkbox__inner::after {
  height: 8px;
  width: 4px;
  left: 5px;
}

.yh-checkbox--small {
  --yh-checkbox-input-height: 12px;
  --yh-checkbox-input-width: 12px;
  --yh-checkbox-font-size: var(--yh-font-size-xs);
  height: 24px;
}
.yh-checkbox--small .yh-checkbox__inner::after {
  height: 6px;
  width: 2px;
  left: 4px;
}

.yh-checkbox:last-of-type {
  margin-right: 0;
}

.yh-checkbox__input.is-checked .yh-checkbox__inner {
  background-color: var(--yh-checkbox-checked-bg-color);
  border-color: var(--yh-checkbox-checked-bg-color);
}
.yh-checkbox__input.is-checked .yh-checkbox__inner::after {
  transform: rotate(45deg) scaleY(1);
  border-color: var(--yh-checkbox-checked-icon-color);
}
.yh-checkbox__input.is-checked + .yh-checkbox__label {
  color: var(--yh-checkbox-checked-text-color);
}

.yh-checkbox__input.is-indeterminate .yh-checkbox__inner {
  background-color: var(--yh-checkbox-checked-bg-color);
  border-color: var(--yh-checkbox-checked-bg-color);
}
.yh-checkbox__input.is-indeterminate .yh-checkbox__inner::before {
  content: "";
  position: absolute;
  display: block;
  background-color: var(--yh-checkbox-checked-icon-color);
  height: 2px;
  transform: scale(0.5);
  left: 0;
  right: 0;
  top: 5px;
}
.yh-checkbox__input.is-indeterminate .yh-checkbox__inner::after {
  display: none;
}

.yh-checkbox__input.is-disabled {
  cursor: not-allowed;
}
.yh-checkbox__input.is-disabled .yh-checkbox__inner {
  background-color: var(--yh-checkbox-disabled-input-fill);
  border-color: var(--yh-checkbox-disabled-border-color);
  cursor: not-allowed;
}
.yh-checkbox__input.is-disabled .yh-checkbox__inner:hover {
  border-color: var(--yh-checkbox-disabled-border-color);
}
.yh-checkbox__input.is-disabled .yh-checkbox__inner::after {
  cursor: not-allowed;
  border-color: var(--yh-checkbox-disabled-icon-color);
}
.yh-checkbox__input.is-disabled + .yh-checkbox__label {
  color: var(--yh-text-color-disabled);
  cursor: not-allowed;
}

.yh-checkbox__input.is-disabled.is-checked .yh-checkbox__inner {
  background-color: var(--yh-checkbox-disabled-checked-input-fill);
  border-color: var(--yh-checkbox-disabled-checked-input-border-color);
}
.yh-checkbox__input.is-disabled.is-checked .yh-checkbox__inner::after {
  transform: rotate(45deg) scaleY(1);
  border-color: var(--yh-checkbox-disabled-checked-icon-color);
}

.yh-checkbox__input.is-disabled.is-indeterminate .yh-checkbox__inner {
  background-color: var(--yh-checkbox-disabled-checked-input-fill);
  border-color: var(--yh-checkbox-disabled-checked-input-border-color);
}
.yh-checkbox__input.is-disabled.is-indeterminate .yh-checkbox__inner::before {
  background-color: var(--yh-checkbox-disabled-checked-icon-color);
}
</style>
