<script setup lang="ts">
// ---------------------------------------------------------------------
// 🔒 AUTOGENERATED @synergy-design-system/vue wrappers for @synergy-design-system/components
// Please do not edit this file directly!
// It will get recreated when running pnpm build.
// ---------------------------------------------------------------------

/**
 * @summary Selects allow you to choose items from a menu of predefined options.
 * @documentation https://synergy-design-system.github.io/?path=/docs/components-syn-select--docs
 * @status stable
 * @since 1.5.0
 *
 * @dependency syn-icon
 * @dependency syn-popup
 * @dependency syn-tag
 *
 * @slot - The listbox options. Must be `<syn-option>` elements. You can use `<syn-divider>` to group items visually.
 * @slot label - The input's label. Alternatively, you can use the `label` attribute.
 * @slot prefix - Used to prepend a presentational icon or similar element to the combobox.
 * @slot suffix - Used to append a presentational icon or similar element to the combobox.
 * @slot clear-icon - An icon to use in lieu of the default clear icon.
 * @slot expand-icon - The icon to show when the control is expanded and collapsed. Rotates on open and close.
 * @slot help-text - Text that describes how to use the input. Alternatively, you can use the `help-text` attribute.
 *
 * @event syn-change - Emitted when the control's value changes.
 * @event syn-clear - Emitted when the control's value is cleared.
 * @event syn-input - Emitted when the control receives input.
 * @event syn-focus - Emitted when the control gains focus.
 * @event syn-blur - Emitted when the control loses focus.
 * @event syn-show - Emitted when the select's menu opens.
 * @event syn-after-show - Emitted after the select's menu opens and all animations are complete.
 * @event syn-hide - Emitted when the select's menu closes.
 * @event syn-after-hide - Emitted after the select's menu closes and all animations are complete.
 * @event syn-invalid - Emitted when the form control has been checked for validity and its constraints aren't satisfied.
 *
 * @csspart form-control - The form control that wraps the label, input, and help text.
 * @csspart form-control-label - The label's wrapper.
 * @csspart form-control-input - The select's wrapper.
 * @csspart form-control-help-text - The help text's wrapper.
 * @csspart combobox - The container the wraps the prefix, suffix, combobox, clear icon, and expand button.
 * @csspart prefix - The container that wraps the prefix slot.
 * @csspart suffix - The container that wraps the suffix slot.
 * @csspart display-input - The element that displays the selected option's label, an `<input>` element.
 * @csspart listbox - The listbox container where options are slotted.
 * @csspart tags - The container that houses option tags when `multiselect` is used.
 * @csspart tag - The individual tags that represent each multiselect option.
 * @csspart tag__base - The tag's base part.
 * @csspart tag__content - The tag's content part.
 * @csspart tag__remove-button - The tag's remove button.
 * @csspart tag__remove-button__base - The tag's remove button base part.
 * @csspart clear-button - The clear button.
 * @csspart expand-icon - The container that wraps the expand icon.
 * @csspart popup - The popup's exported `popup` part. Use this to target the tooltip's popup container.
 */
import { computed, ref } from 'vue';
import '@synergy-design-system/components/components/select/select.js';

import type { SynChangeEvent } from '@synergy-design-system/components';
import type { SynClearEvent } from '@synergy-design-system/components';
import type { SynInputEvent } from '@synergy-design-system/components';
import type { SynFocusEvent } from '@synergy-design-system/components';
import type { SynBlurEvent } from '@synergy-design-system/components';
import type { SynShowEvent } from '@synergy-design-system/components';
import type { SynAfterShowEvent } from '@synergy-design-system/components';
import type { SynHideEvent } from '@synergy-design-system/components';
import type { SynAfterHideEvent } from '@synergy-design-system/components';
import type { SynInvalidEvent } from '@synergy-design-system/components';
import type SynSelect from '@synergy-design-system/components/components/select/select.component.js';

// DOM Reference to the element
const nativeElement = ref<SynSelect>();

defineExpose({
  nativeElement,
});

// Map attributes
const props = defineProps<{
  /**
* The delimiter to use when setting the value when `multiple` is enabled.
The default is a space, but you can set it to a comma or other character.
 */
  delimiter?: SynSelect['delimiter'];

  /**
   * The name of the select, submitted as a name/value pair with form data.
   */
  name?: SynSelect['name'];

  /**
   * The select's size.
   */
  size?: SynSelect['size'];

  /**
   * Placeholder text to show as a hint when the select is empty.
   */
  placeholder?: SynSelect['placeholder'];

  /**
   * Allows more than one option to be selected.
   */
  multiple?: SynSelect['multiple'];

  /**
* The maximum number of selected options to show when `multiple` is true.
* After the maximum, "+n" will be shown to
indicate the number of additional items that are selected.
* Set to 0 to remove the limit.
 */
  maxOptionsVisible?: SynSelect['maxOptionsVisible'];

  /**
   * Disables the select control.
   */
  disabled?: SynSelect['disabled'];

  /**
   * Sets the select to a readonly state.
   */
  readonly?: SynSelect['readonly'];

  /**
   * Adds a clear button when the select is not empty.
   */
  clearable?: SynSelect['clearable'];

  /**
* Indicates whether or not the select is open.
* You can toggle this attribute to show and hide the menu, or you can
use the `show()` and `hide()` methods and this attribute will reflect the select's open state.
 */
  open?: SynSelect['open'];

  /**
   * The select's label.
   * If you need to display HTML, use the `label` slot instead.
   */
  label?: SynSelect['label'];

  /**
* The preferred placement of the select's menu.
* Note that the actual placement may vary as needed to keep the listbox
inside of the viewport.
 */
  placement?: SynSelect['placement'];

  /**
   * The select's help text.
   * If you need to display HTML, use the `help-text` slot instead.
   */
  helpText?: SynSelect['helpText'];

  /**
* By default, form controls are associated with the nearest containing `<form>` element.
* This attribute allows you
to place the form control outside of a form and associate it with the form that has this `id`.
* The form must be in
the same document or shadow root for this to work.
 */
  form?: SynSelect['form'];

  /**
   * The select's required attribute.
   */
  required?: SynSelect['required'];

  /**
* A function that customizes the tags to be rendered when multiple=true.
* The first argument is the option, the second
is the current tag's index.
* The function should return either a Lit TemplateResult or a string containing trusted HTML of the symbol to render at
the specified value.
 */
  getTag?: SynSelect['getTag'];

  /**
* The current value of the select, submitted as a name/value pair with form data.
* When `multiple` is enabled, the
value attribute will be a space-delimited list of values based on the options selected, and the value property will
be an array.
* **For this reason, values must not contain spaces.**
 */
  value?: SynSelect['value'];

  /**
   * Support for two way data binding
   */
  modelValue?: SynSelect['value'];
}>();

// Make sure prop binding only forwards the props that are actually there.
// This is needed because :param="param" also adds an empty attribute
// when using web-components, which breaks optional arguments like size in SynInput
// @see https://github.com/vuejs/core/issues/5190#issuecomment-1003112498
const visibleProps = computed(() =>
  Object.fromEntries(
    Object.entries(props).filter(([, value]) => typeof value !== 'undefined'),
  ),
);

// Map events
defineEmits<{
  /**
   * Emitted when the control's value changes.
   */
  'syn-change': [e: SynChangeEvent];

  /**
   * Emitted when the control's value is cleared.
   */
  'syn-clear': [e: SynClearEvent];

  /**
   * Emitted when the control receives input.
   */
  'syn-input': [e: SynInputEvent];

  /**
   * Emitted when the control gains focus.
   */
  'syn-focus': [e: SynFocusEvent];

  /**
   * Emitted when the control loses focus.
   */
  'syn-blur': [e: SynBlurEvent];

  /**
   * Emitted when the select's menu opens.
   */
  'syn-show': [e: SynShowEvent];

  /**
   * Emitted after the select's menu opens and all animations are complete.
   */
  'syn-after-show': [e: SynAfterShowEvent];

  /**
   * Emitted when the select's menu closes.
   */
  'syn-hide': [e: SynHideEvent];

  /**
   * Emitted after the select's menu closes and all animations are complete.
   */
  'syn-after-hide': [e: SynAfterHideEvent];

  /**
   * Emitted when the form control has been checked for validity and its constraints aren't satisfied.
   */
  'syn-invalid': [e: SynInvalidEvent];

  /**
   * Support for two way data binding
   */
  'update:modelValue': [newValue: SynSelect['value']];
}>();
</script>

<script lang="ts">
export type { SynChangeEvent } from '@synergy-design-system/components';
export type { SynClearEvent } from '@synergy-design-system/components';
export type { SynInputEvent } from '@synergy-design-system/components';
export type { SynFocusEvent } from '@synergy-design-system/components';
export type { SynBlurEvent } from '@synergy-design-system/components';
export type { SynShowEvent } from '@synergy-design-system/components';
export type { SynAfterShowEvent } from '@synergy-design-system/components';
export type { SynHideEvent } from '@synergy-design-system/components';
export type { SynAfterHideEvent } from '@synergy-design-system/components';
export type { SynInvalidEvent } from '@synergy-design-system/components';
</script>

<template>
  <syn-select
    @syn-change="$emit('syn-change', $event)"
    @syn-clear="$emit('syn-clear', $event)"
    @syn-input="
      $emit('update:modelValue', ($event.target as SynSelect).value);
      $emit('syn-input', $event);
    "
    @syn-focus="$emit('syn-focus', $event)"
    @syn-blur="$emit('syn-blur', $event)"
    @syn-show="$emit('syn-show', $event)"
    @syn-after-show="$emit('syn-after-show', $event)"
    @syn-hide="$emit('syn-hide', $event)"
    @syn-after-hide="$emit('syn-after-hide', $event)"
    @syn-invalid="$emit('syn-invalid', $event)"
    :value="
      typeof props.modelValue !== 'undefined'
        ? props.modelValue
        : typeof props.value !== 'undefined'
          ? props.value
          : undefined
    "
    v-bind="visibleProps"
    ref="nativeElement">
    <slot></slot>
  </syn-select>
</template>
