UNPKG

carbon-custom-elements

Version:

A Carbon Design System variant that's as easy to use as native HTML elements, with no framework tax, no framework silo.

1 lines 6.6 kB
{"version":3,"sources":["globals/internal/radio-group-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,oBAAY,oBAAoB;IAC9B;;OAEG;IACH,QAAQ,KAAK;IAEb;;OAEG;IACH,OAAO,IAAI;CACZ;AAED,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,uBAAuB,CAAC,KAAK,EAAE,0BAA0B,GAAG,MAAM,CAAC;IAEnE;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAED,aAAK,kBAAkB,GAAG,gBAAgB,GAAG,0BAA0B,CAAC;AAExE;;;GAGG;AACH,cAAM,iBAAiB;IACrB;;OAEG;IACH,OAAO,CAAC,OAAO,CAAmD;IAElE,OAAO;IAIP;;;;;;OAMG;IACH,iBAAiB,CAAC,KAAK,EAAE,kBAAkB;IAc3C;;;OAGG;IACH,cAAc,CAAC,KAAK,EAAE,kBAAkB;IAmBxC;;;;OAIG;IACH,GAAG,CAAC,KAAK,EAAE,kBAAkB;IAY7B;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,kBAAkB,EAAE,IAAI,GAAE,MAAmB;IAK3D;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,kBAAkB;IAgBhC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,oBAAoB;IAWnE;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiB;IAE1C;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ;CAI9B;AAED,eAAe,iBAAiB,CAAC","file":"radio-group-manager.d.ts","sourcesContent":["/**\n * @license\n *\n * Copyright IBM Corp. 2019\n *\n * This source code is licensed under the Apache-2.0 license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * The navigation direction.\n */\nexport enum NAVIGATION_DIRECTION {\n /**\n * Navigating backward.\n */\n BACKWARD = -1,\n\n /**\n * Navigating forward.\n */\n FORWARD = 1,\n}\n\nexport interface ManagedRadioButtonDelegate {\n /**\n * `true` if this radio button is selected.\n */\n checked: boolean;\n\n /**\n * The tab index.\n */\n tabIndex: number;\n\n /**\n * The name of the radio group.\n */\n name: string;\n\n /**\n * @param other A node to compare this radio button's DOM position in document with.\n * @returns\n * An integer value, the same format as `Node.compareDocumentPosition` does,\n * whose bits represent the calling this radio button's relationship to the given node within the document.\n */\n compareDocumentPosition(other: ManagedRadioButtonDelegate): number;\n\n /**\n * Focuses on the radio button.\n */\n focus(): void;\n}\n\ntype ManagedRadioButton = HTMLInputElement | ManagedRadioButtonDelegate;\n\n/**\n * An object that manages radio groups in a document.\n * There must be only one instance for one document.\n */\nclass RadioGroupManager {\n /**\n * Radio groups, keyed by their names.\n */\n private _groups: { [name: string]: Set<ManagedRadioButton> } = {};\n\n private constructor(document: Document) {\n (this.constructor as typeof RadioGroupManager)._instances.set(document, this);\n }\n\n /**\n * @param radio A radio button.\n * @returns\n * `true` if the given radio button should be focusable, which is either:\n * - The radio button is selected\n * - No radio button is selected and the radio button is first one in the radio group\n */\n shouldBeFocusable(radio: ManagedRadioButton) {\n if (radio.checked) {\n return true;\n }\n const { name } = radio;\n const group = this._groups[name];\n const hasSelectedItemInGroup = group && Array.from(group).some(item => item.checked);\n if (hasSelectedItemInGroup) {\n return false;\n }\n const isFirstInGroup = !group || group.size === 1 || this.getSortedGroup(radio)[0] === radio;\n return isFirstInGroup;\n }\n\n /**\n * @param radio A radio button.\n * @returns The sorted radio group the given radio button is in.\n */\n getSortedGroup(radio: ManagedRadioButton) {\n const group = this._groups[radio.name];\n return (\n group &&\n Array.from(group).sort((lhs, rhs) => {\n const comparisonResult = (lhs as ManagedRadioButtonDelegate).compareDocumentPosition(rhs as ManagedRadioButtonDelegate);\n // eslint-disable-next-line no-bitwise\n if (comparisonResult & Node.DOCUMENT_POSITION_FOLLOWING || comparisonResult & Node.DOCUMENT_POSITION_CONTAINED_BY) {\n return -1;\n }\n // eslint-disable-next-line no-bitwise\n if (comparisonResult & Node.DOCUMENT_POSITION_PRECEDING || comparisonResult & Node.DOCUMENT_POSITION_CONTAINS) {\n return 1;\n }\n return 0;\n })\n );\n }\n\n /**\n * Manages a radio button.\n * @param radio The radio button to manage.\n * @returns This object.\n */\n add(radio: ManagedRadioButton) {\n const { name } = radio;\n if (name) {\n const groups = this._groups;\n if (!groups[name]) {\n groups[name] = new Set<ManagedRadioButton>();\n }\n groups[name].add(radio);\n }\n return this;\n }\n\n /**\n * Unmanages a radio button.\n * @param radio The radio button to unmanage.\n * @param name The old name of the radio button to unmanage.\n * @returns `true` if `element` was actually managed.\n */\n delete(radio: ManagedRadioButton, name: string = radio.name) {\n const group = this._groups[name];\n return !group ? false : group.delete(radio);\n }\n\n /**\n * Selects or focuses on a radio button.\n * @param radio The radio button to select.\n */\n select(radio: ManagedRadioButton) {\n const group = this._groups[radio.name];\n if (group) {\n // Updates the state of the one being selected up-front to avoid the state of no radio button is selected\n radio.checked = true;\n radio.tabIndex = 0;\n radio.focus();\n group.forEach(item => {\n if (radio !== item) {\n item.checked = false;\n item.tabIndex = -1;\n }\n });\n }\n }\n\n /**\n * @param radio The currently selected radio button.\n * @param direction The direction to navigate to.\n * @returns The radio button that should be selected next.\n */\n navigate(radio: ManagedRadioButton, direction: NAVIGATION_DIRECTION) {\n const sortedGroup = this.getSortedGroup(radio);\n let newIndex = sortedGroup.indexOf(radio) + direction;\n if (newIndex < 0) {\n newIndex = sortedGroup.length - 1;\n } else if (newIndex >= sortedGroup.length) {\n newIndex = 0;\n }\n return sortedGroup[newIndex];\n }\n\n /**\n * `RadioGroupManager` instances associated with documents.\n */\n private static _instances = new WeakMap();\n\n /**\n * @param document A document element.\n * @returns The `RadioGroupManager` instance associated with the given document.\n */\n static get(document: Document) {\n const found = this._instances.get(document);\n return found || new RadioGroupManager(document);\n }\n}\n\nexport default RadioGroupManager;\n"]}