UNPKG

@hashicorp/design-system-components

Version:
124 lines (121 loc) 8.01 kB
import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { schedule } from '@ember/runloop'; import { modifier } from 'ember-modifier'; import { concat, hash } from '@ember/helper'; import { guidFor } from '@ember/object/internals'; import { eq } from 'ember-truth-helpers'; import style from 'ember-style-modifier'; import { registerAriaDescriptionElement, unregisterAriaDescriptionElement, ariaDescribedBy } from '../../../../utils/hds-aria-described-by.js'; import HdsAlert from '../../alert/index.js'; import HdsFormError from '../error/index.js'; import HdsFormHelperText from '../helper-text/index.js'; import HdsFormKeyValueInputsDeleteRowButton from './delete-row-button.js'; import HdsFormKeyValueInputsField from './field.js'; import HdsFormKeyValueInputsGeneric from './generic.js'; import HdsFormLegend from '../legend/index.js'; import HdsYield from '../../yield/index.js'; import HdsFormKeyValueInputsAddRowButton from './add-row-button.js'; import { precompileTemplate } from '@ember/template-compilation'; import { setComponentTemplate } from '@ember/component'; import { c, g, i } from 'decorator-transforms/runtime'; /** * Copyright IBM Corp. 2021, 2025 * SPDX-License-Identifier: MPL-2.0 */ const KEY_VALUE_INPUTS_FIELD_SELECTOR = '.hds-form-key-value-inputs__field'; const KEY_VALUE_INPUTS_GENERIC_SELECTOR = '.hds-form-key-value-inputs__generic-container'; const KEY_VALUE_INPUTS_FIRST_ROW_SELECTOR = '.hds-form-key-value-inputs__row--first'; const KEY_VALUE_INPUTS_DELETE_ROW_CONTAINER_SELECTOR = '.hds-form-key-value-inputs__delete-row-button-container'; const HdsFormKeyValueInputs = c(class HdsFormKeyValueInputs extends Component { _element; static { g(this.prototype, "_gridTemplateColumns", [tracked], function () { return ''; }); } #_gridTemplateColumns = (i(this, "_gridTemplateColumns"), void 0); // this is not a specific DOM id, but a value that is used to "glue" together // different fieldsset-related elements (legend, helper text, error) with the fieldset itself get glueId() { return guidFor(this); } _setUpColumn = () => { // eslint-disable-next-line ember/no-runloop schedule('afterRender', () => { this._updateColumns(); }); }; _removeColumn = () => { // eslint-disable-next-line ember/no-runloop schedule('afterRender', () => { this._updateColumns(); }); }; appendDescriptor = element => { registerAriaDescriptionElement(this, element); }; removeDescriptor = element => { unregisterAriaDescriptionElement(this, element); }; _setUpKeyValueInputs = modifier(element => { this._element = element; }); // Update the column array based on how they are ordered in the DOM _updateColumns = () => { const columns = this._element.querySelector(KEY_VALUE_INPUTS_FIRST_ROW_SELECTOR)?.querySelectorAll(`${KEY_VALUE_INPUTS_FIELD_SELECTOR}, ${KEY_VALUE_INPUTS_GENERIC_SELECTOR}, ${KEY_VALUE_INPUTS_DELETE_ROW_CONTAINER_SELECTOR}`); let updatedGridTemplateColumns = ''; columns?.forEach((column, index) => { const columnElement = column; // FIELD if ( // do substring to remove the leading dot from the class selector column.classList.contains(KEY_VALUE_INPUTS_FIELD_SELECTOR.substring(1))) { if (columnElement.dataset['width']) { updatedGridTemplateColumns += `${columnElement.dataset['width']} `; } else { updatedGridTemplateColumns += '1fr '; } } // GENERIC if ( // do substring to remove the leading dot from the class selector column.classList.contains(KEY_VALUE_INPUTS_GENERIC_SELECTOR.substring(1))) { updatedGridTemplateColumns += 'auto '; // Set grid-column so generic content appears in the correct column when grid-row is set; otherwise, browsers default it to the first column. columnElement.style.setProperty('--hds-key-value-inputs-column-index', `${index + 1}`); } // DELETE BUTTON if (column.classList.contains(KEY_VALUE_INPUTS_DELETE_ROW_CONTAINER_SELECTOR.substring(1))) { // Set grid-column so generic content appears in the correct column when grid-row is set; otherwise, browsers default it to the first column. columnElement.style.setProperty('--hds-key-value-inputs-column-index', `${index + 1}`); } }); // we always set aside the space for the delete button (it's always the last element) // even when it's not rendered, to avoid layout shifts when moving to/from an empty state updatedGridTemplateColumns += '2.25rem '; this._gridTemplateColumns = updatedGridTemplateColumns; }; static { setComponentTemplate(precompileTemplate("<fieldset class=\"hds-form-key-value-inputs\" ...attributes {{style --hds-key-value-inputs-columns=this._gridTemplateColumns}} {{!-- need to set aria-labelledby because the legend is not a direct descendant of the fieldset --}} aria-labelledby=\"legend-{{this.glueId}}\" {{!-- @glint-expect-error --}} aria-describedby={{this.ariaDescribedBy}} tabindex=\"-1\" {{this._setUpKeyValueInputs}}>\n <div class=\"hds-form-key-value-inputs__header\">\n {{yield (hash Legend=(component HdsFormLegend contextualClass=\"hds-form-key-value-inputs__legend\" id=(concat \"legend-\" this.glueId) isOptional=@isOptional isRequired=@isRequired) HelperText=(component HdsFormHelperText contextualClass=\"hds-form-key-value-inputs__helper-text\" controlId=this.glueId onInsert=this.appendDescriptor) Generic=HdsYield) to=\"header\"}}\n </div>\n\n {{#if (eq @data.length 0)}}\n <div class=\"hds-form-key-value-inputs__row hds-form-key-value-inputs__row--first\">\n {{yield (hash Field=(component HdsFormKeyValueInputsField onInsert=this._setUpColumn onRemove=this._removeColumn rowIndex=0) Generic=(component HdsFormKeyValueInputsGeneric onInsert=this._setUpColumn onRemove=this._removeColumn) rowData=undefined rowIndex=0) to=\"row\"}}\n\n {{!-- leaving as a separate yield to keep the delete row button at the end of the row --}}\n {{yield (hash DeleteRowButton=(component HdsFormKeyValueInputsDeleteRowButton returnFocusTo=this._element onInsert=this._setUpColumn onRemove=this._removeColumn rowData=undefined rowIndex=0)) to=\"row\"}}\n </div>\n {{/if}}\n\n {{#each @data as |item index|}}\n <div class=\"hds-form-key-value-inputs__row\n {{if (eq index 0) \"hds-form-key-value-inputs__row--first\"}}\">\n {{yield (hash Field=(component HdsFormKeyValueInputsField onInsert=this._setUpColumn onRemove=this._removeColumn rowIndex=index) Generic=(component HdsFormKeyValueInputsGeneric onInsert=this._setUpColumn onRemove=this._removeColumn) rowData=item rowIndex=index) to=\"row\"}}\n\n {{!-- leaving as a separate yield to keep the delete row button at the end of the row --}}\n {{yield (hash DeleteRowButton=(component HdsFormKeyValueInputsDeleteRowButton onInsert=this._setUpColumn onRemove=this._removeColumn returnFocusTo=this._element rowData=item rowIndex=index) rowData=item rowIndex=index) to=\"row\"}}\n </div>\n {{/each}}\n\n <div class=\"hds-form-key-value-inputs__footer\">\n {{yield (hash Alert=(component HdsAlert color=\"neutral\" type=\"compact\") AddRowButton=HdsFormKeyValueInputsAddRowButton Error=(component HdsFormError contextualClass=\"hds-form-key-value-inputs__error\" controlId=this.glueId onInsert=this.appendDescriptor onRemove=this.removeDescriptor)) to=\"footer\"}}\n </div>\n</fieldset>", { strictMode: true, scope: () => ({ style, hash, HdsFormLegend, concat, HdsFormHelperText, HdsYield, eq, HdsFormKeyValueInputsField, HdsFormKeyValueInputsGeneric, HdsFormKeyValueInputsDeleteRowButton, HdsAlert, HdsFormKeyValueInputsAddRowButton, HdsFormError }) }), this); } }, [ariaDescribedBy]); export { HdsFormKeyValueInputs as default }; //# sourceMappingURL=index.js.map