<commit_before>import './CalendarMonthNavigator.js'
import './SeamlessButton.js';
import { calendar } from './elix.js';
import { getSuperProperty } from './workarounds.js';
import { merge } from './updates.js';
import { forwardFocus, stateChanged } from './utilities.js';
import * as symbols from './symbols.js';
import * as template from './template.js';
import CalendarElementMixin from './CalendarElementMixin.js';
import ComboBox from './ComboBox.js';
import DateInput from './DateInput.js';


const previousStateKey = Symbol('previousState');


const Base =
  CalendarElementMixin(
    ComboBox
  );

  
class DateComboBox extends Base {

  componentDidMount() {
    if (super.componentDidMount) { super.componentDidMount(); }
    if (this.$.todayButton instanceof HTMLElement && this.$.input instanceof HTMLElement) {
      forwardFocus(this.$.todayButton, this.$.input);
    }
  }

  componentDidUpdate(previousState) {
    if (super.componentDidUpdate) { super.componentDidUpdate(previousState); }
    this.$.calendar.addEventListener('date-changed', event => {
      this[symbols.raiseChangeEvents] = true;
      /** @type {any} */
      const cast = event;
      const date = cast.detail.date;
      const value = formatDate(this.state, date);
      this.setState({
        date,
        value
      });
      this[symbols.raiseChangeEvents] = false;
    });
    this.$.calendar.addEventListener('mousedown', event => {
      // Keep focus on input.
      event.preventDefault();
    });
    this.$.input.addEventListener('date-changed', event => {
      this[symbols.raiseChangeEvents] = true;
      /** @type {any} */
      const cast = event.target;
      this.setState({
        date: cast.date,
        value: cast.value
      });
      this[symbols.raiseChangeEvents] = false;
    });
    this.$.todayButton.addEventListener('mousedown', event => {
      this[symbols.raiseChangeEvents] = true;
      const date = calendar.today();
      const value = formatDate(date);
      this.setState({
        date,
        value
      });
      this[symbols.raiseChangeEvents] = false;
    });
  }

  get dateTimeFormatOptions() {
    return this.state.dateTimeFormatOptions;
  }
  set dateTimeFormatOptions(dateTimeFormatOptions) {
    this.setState({
      dateTimeFormatOptions
    });
  }

  get defaultState() {
    const dateTimeFormatOptions = {
      day: 'numeric',
      month: 'numeric',
      year: 'numeric'
    };
    return Object.assign({}, super.defaultState, {
      date: null,
      dateTimeFormatOptions,
      inputRole: DateInput
    });
  }

  refineState(state) {
    let result = super.refineState ? super.refineState(state) : true;
    state[previousStateKey] = state[previousStateKey] || {
      opened: false,
      value: null
    };
    const changed = stateChanged(state, state[previousStateKey]);
    const { date, opened } = state;
    const closing = changed.opened && !opened;
    if (closing) {
      // Update value from date if we we're closing.
      if (date !== null) {
        const formattedDate = formatDate(state, date);
        if (state.value !== formattedDate) {
          state.value = formattedDate;
          result = false;
        }
      } else if (state.value !== '') {
        state.value = '';
        result = false;
      }
    }
    return result;
  }

  get [symbols.template]() {
    // Next line is same as: const result = super[symbols.template]
    const result = getSuperProperty(this, DateComboBox, symbols.template);

    // Replace default slot with calendar.
    const calendarTemplate = template.html`
      <style>
        #calendar {
          /* flex: 1; */
          width: 100%;
        }

        #todayButton {
          padding: 0.5em;
        }
      </style><commit_msg>Wire up event handlers once instead of a billion times. (D'oh.)<commit_after>import './CalendarMonthNavigator.js'
import './SeamlessButton.js';
import { calendar } from './elix.js';
import { getSuperProperty } from './workarounds.js';
import { merge } from './updates.js';
import { forwardFocus, stateChanged } from './utilities.js';
import * as symbols from './symbols.js';
import * as template from './template.js';
import CalendarElementMixin from './CalendarElementMixin.js';
import ComboBox from './ComboBox.js';
import DateInput from './DateInput.js';


const previousStateKey = Symbol('previousState');


const Base =
  CalendarElementMixin(
    ComboBox
  );

  
class DateComboBox extends Base {

  componentDidMount() {
    if (super.componentDidMount) { super.componentDidMount(); }
    this.$.calendar.addEventListener('date-changed', event => {
      this[symbols.raiseChangeEvents] = true;
      /** @type {any} */
      const cast = event;
      const date = cast.detail.date;
      const value = formatDate(this.state, date);
      this.setState({
        date,
        value
      });
      this[symbols.raiseChangeEvents] = false;
    });
    this.$.calendar.addEventListener('mousedown', event => {
      this[symbols.raiseChangeEvents] = true;
      this.close();
      event.preventDefault(); // Keep focus on input.
      this[symbols.raiseChangeEvents] = false;
    });
    this.$.input.addEventListener('date-changed', event => {
      this[symbols.raiseChangeEvents] = true;
      /** @type {any} */
      const cast = event.target;
      this.setState({
        date: cast.date,
        value: cast.value
      });
      this[symbols.raiseChangeEvents] = false;
    });
    this.$.todayButton.addEventListener('mousedown', event => {
      this[symbols.raiseChangeEvents] = true;
      const date = calendar.today();
      const value = formatDate(date);
      this.setState({
        date,
        selectText: true,
        value
      });
      this.close();
      event.preventDefault(); // Keep focus on input.
      this[symbols.raiseChangeEvents] = false;
    });
    if (this.$.todayButton instanceof HTMLElement && this.$.input instanceof HTMLElement) {
      forwardFocus(this.$.todayButton, this.$.input);
    }
  }

  get dateTimeFormatOptions() {
    return this.state.dateTimeFormatOptions;
  }
  set dateTimeFormatOptions(dateTimeFormatOptions) {
    this.setState({
      dateTimeFormatOptions
    });
  }

  get defaultState() {
    const dateTimeFormatOptions = {
      day: 'numeric',
      month: 'numeric',
      year: 'numeric'
    };
    return Object.assign({}, super.defaultState, {
      date: null,
      dateTimeFormatOptions,
      inputRole: DateInput
    });
  }

  refineState(state) {
    let result = super.refineState ? super.refineState(state) : true;
    state[previousStateKey] = state[previousStateKey] || {
      opened: false,
      value: null
    };
    const changed = stateChanged(state, state[previousStateKey]);
    const { date, opened } = state;
    const closing = changed.opened && !opened;
    if (closing) {
      // Update value from date if we we're closing.
      if (date !== null) {
        const formattedDate = formatDate(state, date);
        if (state.value !== formattedDate) {
          state.value = formattedDate;
          result = false;
        }
      } else if (state.value !== '') {
        state.value = '';
        result = false;
      }
    }
    return result;
  }

  get [symbols.template]() {
    // Next line is same as: const result = super[symbols.template]
    const result = getSuperProperty(this, DateComboBox, symbols.template);

    // Replace default slot with calendar.
    const calendarTemplate = template.html`
      <style>
        #calendar {
          /* flex: 1; */
          width: 100%;
        }

        #todayButton {
          border: 1px solid transparent;
          padding: 0.5em;
        }

        #todayButton:hover {
          border-color: gray;
        }
      </style>
{'fraction_non_alphanumeric': 0.13034518289541475, 'fraction_numerical': 0.0016743946419371459, 'mean_word_length': 2.5472818638647783, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '876221', 'n_tokens_mistral': 2266, 'n_tokens_neox': 2206, 'n_words': 515}