calcite-radio-button.entry.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*!
  2. * All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
  4. * v1.0.0-beta.82
  5. */
  6. import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-8ece2564.js';
  7. import { g as guid } from './guid-b4461004.js';
  8. import { a as getElementDir, f as focusElement, t as toAriaBoolean } from './dom-da697a3f.js';
  9. import { c as connectLabel, d as disconnectLabel, g as getLabelText } from './label-50132b90.js';
  10. import { c as connectForm, d as disconnectForm, H as HiddenFormInputSlot } from './form-bca481e1.js';
  11. import { g as getRoundRobinIndex } from './array-1655bbf7.js';
  12. import { u as updateHostInteraction } from './interactive-cb5bf285.js';
  13. const CSS = {
  14. container: "container"
  15. };
  16. const radioButtonCss = "@-webkit-keyframes in{0%{opacity:0}100%{opacity:1}}@keyframes in{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes in-down{0%{opacity:0;-webkit-transform:translate3D(0, -5px, 0);transform:translate3D(0, -5px, 0)}100%{opacity:1;-webkit-transform:translate3D(0, 0, 0);transform:translate3D(0, 0, 0)}}@keyframes in-down{0%{opacity:0;-webkit-transform:translate3D(0, -5px, 0);transform:translate3D(0, -5px, 0)}100%{opacity:1;-webkit-transform:translate3D(0, 0, 0);transform:translate3D(0, 0, 0)}}@-webkit-keyframes in-up{0%{opacity:0;-webkit-transform:translate3D(0, 5px, 0);transform:translate3D(0, 5px, 0)}100%{opacity:1;-webkit-transform:translate3D(0, 0, 0);transform:translate3D(0, 0, 0)}}@keyframes in-up{0%{opacity:0;-webkit-transform:translate3D(0, 5px, 0);transform:translate3D(0, 5px, 0)}100%{opacity:1;-webkit-transform:translate3D(0, 0, 0);transform:translate3D(0, 0, 0)}}@-webkit-keyframes in-scale{0%{opacity:0;-webkit-transform:scale3D(0.95, 0.95, 1);transform:scale3D(0.95, 0.95, 1)}100%{opacity:1;-webkit-transform:scale3D(1, 1, 1);transform:scale3D(1, 1, 1)}}@keyframes in-scale{0%{opacity:0;-webkit-transform:scale3D(0.95, 0.95, 1);transform:scale3D(0.95, 0.95, 1)}100%{opacity:1;-webkit-transform:scale3D(1, 1, 1);transform:scale3D(1, 1, 1)}}:root{--calcite-animation-timing:calc(150ms * var(--calcite-internal-duration-factor));--calcite-internal-duration-factor:var(--calcite-duration-factor, 1);--calcite-internal-animation-timing-fast:calc(100ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-medium:calc(200ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-slow:calc(300ms * var(--calcite-internal-duration-factor))}.calcite-animate{opacity:0;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:var(--calcite-animation-timing);animation-duration:var(--calcite-animation-timing)}.calcite-animate__in{-webkit-animation-name:in;animation-name:in}.calcite-animate__in-down{-webkit-animation-name:in-down;animation-name:in-down}.calcite-animate__in-up{-webkit-animation-name:in-up;animation-name:in-up}.calcite-animate__in-scale{-webkit-animation-name:in-scale;animation-name:in-scale}:root{--calcite-popper-transition:var(--calcite-animation-timing)}:host([hidden]){display:none}:host{display:block;cursor:pointer}:host .container{position:relative;outline:2px solid transparent;outline-offset:2px}:host .radio{cursor:pointer;border-radius:9999px;background-color:var(--calcite-ui-foreground-1);-webkit-transition-property:all;transition-property:all;-webkit-transition-duration:150ms;transition-duration:150ms;-webkit-transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transition-timing-function:cubic-bezier(0.4, 0, 0.2, 1);-webkit-box-shadow:inset 0 0 0 1px var(--calcite-ui-border-input);box-shadow:inset 0 0 0 1px var(--calcite-ui-border-input)}:host([hovered]) .radio,:host(:not([checked])[focused]:not([disabled])) .radio{-webkit-box-shadow:inset 0 0 0 2px var(--calcite-ui-brand);box-shadow:inset 0 0 0 2px var(--calcite-ui-brand)}:host([disabled]){pointer-events:none;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;opacity:var(--calcite-ui-opacity-disabled)}:host([disabled]) .radio{cursor:default;opacity:var(--calcite-ui-opacity-disabled)}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}:host([hovered][disabled]) .radio{-webkit-box-shadow:inset 0 0 0 1px var(--calcite-ui-border-input);box-shadow:inset 0 0 0 1px var(--calcite-ui-border-input)}:host([scale=s]){--calcite-radio-size:var(--calcite-font-size--2)}:host([scale=m]){--calcite-radio-size:var(--calcite-font-size--1)}:host([scale=l]){--calcite-radio-size:var(--calcite-font-size-0)}.radio{height:var(--calcite-radio-size);max-width:var(--calcite-radio-size);min-width:var(--calcite-radio-size)}:host([scale=s][checked]) .radio,:host([hovered][scale=s][checked][disabled]) .radio{-webkit-box-shadow:inset 0 0 0 4px var(--calcite-ui-brand);box-shadow:inset 0 0 0 4px var(--calcite-ui-brand)}:host([scale=s][focused][checked]:not([disabled])) .radio{-webkit-box-shadow:inset 0 0 0 4px var(--calcite-ui-brand), 0 0 0 2px var(--calcite-ui-foreground-1), 0 0 0 4px var(--calcite-ui-brand);box-shadow:inset 0 0 0 4px var(--calcite-ui-brand), 0 0 0 2px var(--calcite-ui-foreground-1), 0 0 0 4px var(--calcite-ui-brand)}:host([scale=m][checked]) .radio,:host([hovered][scale=m][checked][disabled]) .radio{-webkit-box-shadow:inset 0 0 0 5px var(--calcite-ui-brand);box-shadow:inset 0 0 0 5px var(--calcite-ui-brand)}:host([scale=m][focused][checked]:not([disabled])) .radio{-webkit-box-shadow:inset 0 0 0 5px var(--calcite-ui-brand), 0 0 0 2px var(--calcite-ui-foreground-1), 0 0 0 4px var(--calcite-ui-brand);box-shadow:inset 0 0 0 5px var(--calcite-ui-brand), 0 0 0 2px var(--calcite-ui-foreground-1), 0 0 0 4px var(--calcite-ui-brand)}:host([scale=l][checked]) .radio,:host([hovered][scale=l][checked][disabled]) .radio{-webkit-box-shadow:inset 0 0 0 6px var(--calcite-ui-brand);box-shadow:inset 0 0 0 6px var(--calcite-ui-brand)}:host([scale=l][focused][checked]:not([disabled])) .radio{-webkit-box-shadow:inset 0 0 0 6px var(--calcite-ui-brand), 0 0 0 2px var(--calcite-ui-foreground-1), 0 0 0 4px var(--calcite-ui-brand);box-shadow:inset 0 0 0 6px var(--calcite-ui-brand), 0 0 0 2px var(--calcite-ui-foreground-1), 0 0 0 4px var(--calcite-ui-brand)}@media (forced-colors: active){:host([checked]) .radio::after,:host([checked][disabled]) .radio::after{content:\"\";width:var(--calcite-radio-size);height:var(--calcite-radio-size);background-color:windowText;display:block}}::slotted(input[slot=hidden-form-input]){bottom:0 !important;left:0 !important;margin:0 !important;opacity:0 !important;outline:none !important;padding:0 !important;position:absolute !important;right:0 !important;top:0 !important;-webkit-transform:none !important;transform:none !important;-webkit-appearance:none !important;z-index:-1 !important}";
  17. const RadioButton = class {
  18. constructor(hostRef) {
  19. registerInstance(this, hostRef);
  20. this.calciteInternalRadioButtonBlur = createEvent(this, "calciteInternalRadioButtonBlur", 7);
  21. this.calciteRadioButtonChange = createEvent(this, "calciteRadioButtonChange", 7);
  22. this.calciteInternalRadioButtonCheckedChange = createEvent(this, "calciteInternalRadioButtonCheckedChange", 7);
  23. this.calciteInternalRadioButtonFocus = createEvent(this, "calciteInternalRadioButtonFocus", 7);
  24. //--------------------------------------------------------------------------
  25. //
  26. // Properties
  27. //
  28. //--------------------------------------------------------------------------
  29. /** The checked state of the radio button. */
  30. this.checked = false;
  31. /** The disabled state of the radio button. */
  32. this.disabled = false;
  33. /**
  34. * The focused state of the radio button.
  35. * @internal
  36. */
  37. this.focused = false;
  38. /** The radio button's hidden status. When a radio button is hidden it is not focusable or checkable. */
  39. this.hidden = false;
  40. /**
  41. * The hovered state of the radio button.
  42. * @internal
  43. */
  44. this.hovered = false;
  45. /** Requires that a value is selected for the radio button group before the parent form will submit. */
  46. this.required = false;
  47. /** The scale (size) of the radio button. `scale` is passed as a property automatically from `calcite-radio-button-group`. */
  48. this.scale = "m";
  49. //--------------------------------------------------------------------------
  50. //
  51. // Private Methods
  52. //
  53. //--------------------------------------------------------------------------
  54. this.selectItem = (items, selectedIndex) => {
  55. items[selectedIndex].click();
  56. };
  57. this.queryButtons = () => {
  58. return Array.from(this.rootNode.querySelectorAll("calcite-radio-button:not([hidden])")).filter((radioButton) => radioButton.name === this.name);
  59. };
  60. this.isDefaultSelectable = () => {
  61. const radioButtons = this.queryButtons();
  62. return !radioButtons.some((radioButton) => radioButton.checked) && radioButtons[0] === this.el;
  63. };
  64. this.check = () => {
  65. if (this.disabled) {
  66. return;
  67. }
  68. this.uncheckAllRadioButtonsInGroup();
  69. this.checked = true;
  70. this.calciteRadioButtonChange.emit();
  71. this.setFocus();
  72. };
  73. this.clickHandler = () => {
  74. this.check();
  75. };
  76. this.setContainerEl = (el) => {
  77. this.containerEl = el;
  78. };
  79. this.handleKeyDown = (event) => {
  80. const keys = ["ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown", " "];
  81. const key = event.key;
  82. const { el } = this;
  83. if (keys.indexOf(key) === -1) {
  84. return;
  85. }
  86. if (key === " ") {
  87. this.check();
  88. return;
  89. }
  90. let adjustedKey = key;
  91. if (getElementDir(el) === "rtl") {
  92. if (key === "ArrowRight") {
  93. adjustedKey = "ArrowLeft";
  94. }
  95. if (key === "ArrowLeft") {
  96. adjustedKey = "ArrowRight";
  97. }
  98. }
  99. const radioButtons = Array.from(this.rootNode.querySelectorAll("calcite-radio-button:not([hidden]")).filter((radioButton) => radioButton.name === this.name);
  100. let currentIndex = 0;
  101. const radioButtonsLength = radioButtons.length;
  102. radioButtons.some((item, index) => {
  103. if (item.checked) {
  104. currentIndex = index;
  105. return true;
  106. }
  107. });
  108. switch (adjustedKey) {
  109. case "ArrowLeft":
  110. case "ArrowUp":
  111. event.preventDefault();
  112. this.selectItem(radioButtons, getRoundRobinIndex(Math.max(currentIndex - 1, -1), radioButtonsLength));
  113. return;
  114. case "ArrowRight":
  115. case "ArrowDown":
  116. event.preventDefault();
  117. this.selectItem(radioButtons, getRoundRobinIndex(currentIndex + 1, radioButtonsLength));
  118. return;
  119. default:
  120. return;
  121. }
  122. };
  123. this.onContainerBlur = () => {
  124. this.focused = false;
  125. this.calciteInternalRadioButtonBlur.emit();
  126. };
  127. this.onContainerFocus = () => {
  128. if (!this.disabled) {
  129. this.focused = true;
  130. this.calciteInternalRadioButtonFocus.emit();
  131. }
  132. };
  133. }
  134. checkedChanged(newChecked) {
  135. if (newChecked) {
  136. this.uncheckOtherRadioButtonsInGroup();
  137. }
  138. this.calciteInternalRadioButtonCheckedChange.emit(newChecked);
  139. }
  140. nameChanged() {
  141. this.checkLastRadioButton();
  142. }
  143. //--------------------------------------------------------------------------
  144. //
  145. // Public Methods
  146. //
  147. //--------------------------------------------------------------------------
  148. /** Sets focus on the component. */
  149. async setFocus() {
  150. if (!this.disabled) {
  151. focusElement(this.containerEl);
  152. }
  153. }
  154. onLabelClick(event) {
  155. if (!this.disabled && !this.hidden) {
  156. this.uncheckOtherRadioButtonsInGroup();
  157. const label = event.currentTarget;
  158. const radioButton = label.for
  159. ? this.rootNode.querySelector(`calcite-radio-button[id="${label.for}"]`)
  160. : label.querySelector(`calcite-radio-button[name="${this.name}"]`);
  161. if (radioButton) {
  162. radioButton.checked = true;
  163. radioButton.focused = true;
  164. }
  165. this.calciteRadioButtonChange.emit();
  166. this.setFocus();
  167. }
  168. }
  169. checkLastRadioButton() {
  170. const radioButtons = this.queryButtons();
  171. const checkedRadioButtons = radioButtons.filter((radioButton) => radioButton.checked);
  172. if ((checkedRadioButtons === null || checkedRadioButtons === void 0 ? void 0 : checkedRadioButtons.length) > 1) {
  173. const lastCheckedRadioButton = checkedRadioButtons[checkedRadioButtons.length - 1];
  174. checkedRadioButtons
  175. .filter((checkedRadioButton) => checkedRadioButton !== lastCheckedRadioButton)
  176. .forEach((checkedRadioButton) => {
  177. checkedRadioButton.checked = false;
  178. checkedRadioButton.emitCheckedChange();
  179. });
  180. }
  181. }
  182. /** @internal */
  183. async emitCheckedChange() {
  184. this.calciteInternalRadioButtonCheckedChange.emit();
  185. }
  186. uncheckAllRadioButtonsInGroup() {
  187. const radioButtons = this.queryButtons();
  188. radioButtons.forEach((radioButton) => {
  189. if (radioButton.checked) {
  190. radioButton.checked = false;
  191. radioButton.focused = false;
  192. }
  193. });
  194. }
  195. uncheckOtherRadioButtonsInGroup() {
  196. const radioButtons = this.queryButtons();
  197. const otherRadioButtons = radioButtons.filter((radioButton) => radioButton.guid !== this.guid);
  198. otherRadioButtons.forEach((otherRadioButton) => {
  199. if (otherRadioButton.checked) {
  200. otherRadioButton.checked = false;
  201. otherRadioButton.focused = false;
  202. }
  203. });
  204. }
  205. getTabIndex() {
  206. if (this.disabled) {
  207. return undefined;
  208. }
  209. return this.checked || this.isDefaultSelectable() ? 0 : -1;
  210. }
  211. //--------------------------------------------------------------------------
  212. //
  213. // Event Listeners
  214. //
  215. //--------------------------------------------------------------------------
  216. mouseenter() {
  217. this.hovered = true;
  218. }
  219. mouseleave() {
  220. this.hovered = false;
  221. }
  222. //--------------------------------------------------------------------------
  223. //
  224. // Lifecycle
  225. //
  226. //--------------------------------------------------------------------------
  227. connectedCallback() {
  228. this.rootNode = this.el.getRootNode();
  229. this.guid = this.el.id || `calcite-radio-button-${guid()}`;
  230. if (this.name) {
  231. this.checkLastRadioButton();
  232. }
  233. connectLabel(this);
  234. connectForm(this);
  235. }
  236. componentDidLoad() {
  237. if (this.focused && !this.disabled) {
  238. this.setFocus();
  239. }
  240. }
  241. disconnectedCallback() {
  242. disconnectLabel(this);
  243. disconnectForm(this);
  244. }
  245. componentDidRender() {
  246. updateHostInteraction(this);
  247. }
  248. // --------------------------------------------------------------------------
  249. //
  250. // Render Methods
  251. //
  252. // --------------------------------------------------------------------------
  253. render() {
  254. const tabIndex = this.getTabIndex();
  255. return (h(Host, { onClick: this.clickHandler, onKeyDown: this.handleKeyDown }, h("div", { "aria-checked": toAriaBoolean(this.checked), "aria-label": getLabelText(this), class: CSS.container, onBlur: this.onContainerBlur, onFocus: this.onContainerFocus, ref: this.setContainerEl, role: "radio", tabIndex: tabIndex }, h("div", { class: "radio" })), h(HiddenFormInputSlot, { component: this })));
  256. }
  257. get el() { return getElement(this); }
  258. static get watchers() { return {
  259. "checked": ["checkedChanged"],
  260. "name": ["nameChanged"]
  261. }; }
  262. };
  263. RadioButton.style = radioButtonCss;
  264. export { RadioButton as calcite_radio_button };