UNPKG

@instawork/design-system

Version:

The design system for Instawork's web apps

129 lines 4.55 kB
import * as $ from 'jquery'; const DATA_CONTROLLER = 'iw-component'; const CUSTOM_COMPONENT_ATTR = 'iw-component'; const CUSTOM_COMPONENT_SELECTOR = `[${CUSTOM_COMPONENT_ATTR}]`; let instanceId = 0; function getIwControllerFn(ctrlClass) { return function getIwController() { return ctrlClass.getController(this.filter(CUSTOM_COMPONENT_SELECTOR).add(this.find(CUSTOM_COMPONENT_SELECTOR))); }; } /** * A base class that handles shared functionality for custom components */ export class CustomComponent { constructor($el) { this.$el = $el; /** * The JQuery-wrapped component host element * @type {JQuery} */ this.$el = $el; /** * The native host element * @type {HTMLElement} */ this.el = $el[0]; this.idPrefix = this.constructor.ID_PREFIX; this.id = this.$el.prop('id') || `${this.idPrefix}--${instanceId++}`; this.$el .prop('id', this.id) .attr(CUSTOM_COMPONENT_ATTR, '') .data(DATA_CONTROLLER, this); if (this.constructor.TEMPLATE) { this.$el.html(this.constructor.TEMPLATE); } } /** * Extend jQuery with the component's jQuery plugin function. */ static loadPlugin() { if (!$.fn.getIwController) { $.fn.getIwController = CustomComponent.jQueryComponentControllerFn(); } } static get ID_PREFIX() { return this.getIdPrefix(); } static getIdPrefix() { return this.COMPONENT_SELECTOR; } static getController($el) { return $el.data(DATA_CONTROLLER); } static bind($el) { return this.getController($el) || new this($el); } static jQueryPlugin(controllerName, extras, preInit) { return Object.assign(this.jQueryInitFn(preInit), { [controllerName]: this, COMPONENT_SELECTOR: this.COMPONENT_SELECTOR, CUSTOM_COMPONENT_ATTR: this.CUSTOM_COMPONENT_ATTR, CUSTOM_COMPONENT_SELECTOR: this.CUSTOM_COMPONENT_SELECTOR, }, extras); } /** * Returns a function that can act as an initializer for the component */ static jQueryInitFn(preInit) { const ctrlClass = this; return function initCustomComponent() { if (typeof preInit === 'function') { preInit.call(this); } return this.filter(ctrlClass.COMPONENT_SELECTOR) .add(this.find(ctrlClass.COMPONENT_SELECTOR)) .each((index, el) => { ctrlClass.bind($(el)); }); }; } static jQueryComponentControllerFn() { return getIwControllerFn(this); } /** * Returns a CSS selector style string with the tag name and ID representing the component host element. * * Example: iw-component#some-id--1 */ getDebugIdentifier() { return this.getDebugIdentifierById(); } getDebugIdentifierById() { const tag = this.$el.prop('tagName').toLocaleLowerCase(); const id = this.$el.attr('id'); return `${tag}#${id}`; } attributeError(attributeName, message, required = false) { return Object.assign(new Error(`The ${required ? "required " : ""}"${attributeName}" attribute on element "${this.getDebugIdentifier()}" ${message}`), { name: 'AttributeError', attributeName, attributeRequired: false, element: this.el, }); } attributeInvalidError(attributeName, reason, value) { return Object.assign(this.attributeError(attributeName, `is invalid: ${reason}`), { name: 'AttributeInvalidError', reason, value, }); } requiredAttributeError(attributeName) { return Object.assign(this.attributeError(attributeName, 'is missing', true), { name: 'AttributeRequiredError', required: true, }); } } CustomComponent.CUSTOM_COMPONENT_ATTR = CUSTOM_COMPONENT_SELECTOR; /** * Returns a selector string that can be used to find elements bound to a {@link CustomComponent} instance. * * The iw-component attribute is automatically added to any component using {@link CustomComponent} so they * can be easily identified. */ CustomComponent.CUSTOM_COMPONENT_SELECTOR = CUSTOM_COMPONENT_SELECTOR; /** * Overridden to return a CSS selector for the host element of the component. * * @abstract */ CustomComponent.COMPONENT_SELECTOR = ''; //# sourceMappingURL=custom-component.js.map