@nuralyui/button 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,13 @@
5
5
  */
6
6
  import { LitElement } from 'lit';
7
7
  import { ButtonType, ButtonShape, IconPosition } from './button.types.js';
8
- declare const NrButtonElement_base: (new (...args: any[]) => import("../../shared/dependency-mixin.js").DependencyAware) & (new (...args: any[]) => import("../../shared/theme-mixin.js").ThemeAware) & typeof LitElement;
8
+ declare const NrButtonElement_base: (new (...args: any[]) => import("./mixins/ripple-mixin.js").RippleCapable) & (new (...args: any[]) => import("./mixins/keyboard-mixin.js").KeyboardCapable) & (new (...args: any[]) => import("./mixins/link-mixin.js").LinkCapable) & (new (...args: any[]) => import("../../shared/dependency-mixin.js").DependencyAware) & (new (...args: any[]) => import("../../shared/theme-mixin.js").ThemeAware) & (new (...args: any[]) => import("../../shared/event-handler-mixin.js").EventHandlerCapable) & typeof LitElement;
9
+ /**
10
+ * - NuralyUIBaseMixin: Core functionality (theme, dependencies, events)
11
+ * - RippleMixin: Ripple effect handling
12
+ * - KeyboardMixin: Keyboard interaction (Enter/Space activation)
13
+ * - LinkMixin: Link-specific behavior for ButtonType.Link
14
+ */
9
15
  export declare class NrButtonElement extends NrButtonElement_base {
10
16
  disabled: boolean;
11
17
  loading: boolean;
@@ -19,9 +25,11 @@ export declare class NrButtonElement extends NrButtonElement_base {
19
25
  href: string;
20
26
  target: string;
21
27
  ripple: boolean;
28
+ buttonAriaLabel: string;
29
+ ariaDescribedBy: string;
30
+ htmlType: string;
22
31
  /**
23
32
  * Required components that must be registered for this component to work properly
24
- * Can be overridden by parent implementations
25
33
  */
26
34
  requiredComponents: string[];
27
35
  /**
@@ -29,16 +37,9 @@ export declare class NrButtonElement extends NrButtonElement_base {
29
37
  */
30
38
  connectedCallback(): void;
31
39
  /**
32
- * Get the appropriate element tag based on button type
33
- */
34
- private getElementTag;
35
- /**
36
- * Get attributes for accessibility and functionality
40
+ * Get common attributes for both button and anchor elements
37
41
  */
38
- private getElementAttributes;
39
- buttonAriaLabel: string;
40
- ariaDescribedBy: string;
41
- htmlType: string;
42
+ private getCommonAttributes;
42
43
  /**
43
44
  * Renders an icon if the hy-icon component is available
44
45
  * @param iconName - The name of the icon to render
@@ -46,13 +47,7 @@ export declare class NrButtonElement extends NrButtonElement_base {
46
47
  */
47
48
  private renderIcon;
48
49
  /**
49
- * Creates ripple effect on button click
50
- * @param event - The click event
51
- */
52
- private createRipple;
53
- /**
54
- * Handle click events with ripple effect
55
- * @param event - The click event
50
+ * Handle comprehensive click events with proper event dispatching
56
51
  */
57
52
  private handleClick;
58
53
  render(): import("lit").TemplateResult<1>;
@@ -1 +1 @@
1
- {"version":3,"file":"button.component.d.ts","sourceRoot":"","sources":["../../../src/components/button/button.component.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,UAAU,EAAW,MAAM,KAAK,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAgB,YAAY,EAAE,MAAM,mBAAmB,CAAC;;AAIxF,qBACa,eAAgB,SAAQ,oBAA6B;IAEhE,QAAQ,UAAS;IAGjB,OAAO,UAAS;IAGhB,IAAI,SAAgB;IAGpB,IAAI,EAAE,UAAU,CAAsB;IAGtC,KAAK,EAAE,WAAW,CAAuB;IAGzC,KAAK,UAAS;IAGd,MAAM,UAAS;IAGf,IAAI,EAAE,MAAM,EAAE,CAAM;IAGpB,YAAY,eAAqB;IAGjC,IAAI,SAAgB;IAGpB,MAAM,SAAgB;IAGtB,MAAM,UAAQ;IAEd;;;OAGG;IACM,kBAAkB,WAAe;IAE1C;;OAEG;IACM,iBAAiB;IAK1B;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoC5B,eAAe,SAAgB;IAG/B,eAAe,SAAgB;IAG/B,QAAQ,SAAgB;IAExB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAWlB;;;OAGG;IACH,OAAO,CAAC,YAAY;IA2BpB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAIV,MAAM;IAwDf,OAAgB,MAAM,4BAAU;CACjC"}
1
+ {"version":3,"file":"button.component.d.ts","sourceRoot":"","sources":["../../../src/components/button/button.component.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,UAAU,EAAW,MAAM,KAAK,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAgB,YAAY,EAAE,MAAM,mBAAmB,CAAC;;AAKxF;;;;;GAKG;AACH,qBACa,eAAgB,SAAQ,oBAMpC;IAGU,QAAQ,UAAS;IAG1B,OAAO,UAAS;IAGhB,IAAI,SAAgB;IAGX,IAAI,EAAE,UAAU,CAAsB;IAG/C,KAAK,EAAE,WAAW,CAAuB;IAGzC,KAAK,UAAS;IAGd,MAAM,UAAS;IAIf,IAAI,EAAE,MAAM,EAAE,CAAM;IAGpB,YAAY,eAAqB;IAIxB,IAAI,SAAgB;IAGpB,MAAM,SAAgB;IAItB,MAAM,UAAQ;IAIvB,eAAe,SAAgB;IAG/B,eAAe,SAAgB;IAG/B,QAAQ,SAAgB;IAExB;;OAEG;IACM,kBAAkB,WAAe;IAE1C;;OAEG;IACM,iBAAiB;IAK1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgB3B;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAWlB;;OAEG;IACH,OAAO,CAAC,WAAW;IA4BV,MAAM;IA8Df,OAAgB,MAAM,4BAAU;CACjC"}
@@ -14,9 +14,17 @@ import { customElement, property } from 'lit/decorators.js';
14
14
  import { EMPTY_STRING } from './button.types.js';
15
15
  import { styles } from './button.style.js';
16
16
  import { NuralyUIBaseMixin } from '../../shared/base-mixin.js';
17
- let NrButtonElement = class NrButtonElement extends NuralyUIBaseMixin(LitElement) {
17
+ import { RippleMixin, KeyboardMixin, LinkMixin } from './mixins/index.js';
18
+ /**
19
+ * - NuralyUIBaseMixin: Core functionality (theme, dependencies, events)
20
+ * - RippleMixin: Ripple effect handling
21
+ * - KeyboardMixin: Keyboard interaction (Enter/Space activation)
22
+ * - LinkMixin: Link-specific behavior for ButtonType.Link
23
+ */
24
+ let NrButtonElement = class NrButtonElement extends RippleMixin(KeyboardMixin(LinkMixin(NuralyUIBaseMixin(LitElement)))) {
18
25
  constructor() {
19
26
  super(...arguments);
27
+ // Button state properties
20
28
  this.disabled = false;
21
29
  this.loading = false;
22
30
  this.size = EMPTY_STRING;
@@ -24,19 +32,22 @@ let NrButtonElement = class NrButtonElement extends NuralyUIBaseMixin(LitElement
24
32
  this.shape = "default" /* ButtonShape.Default */;
25
33
  this.block = false;
26
34
  this.dashed = false;
35
+ // Icon properties
27
36
  this.icon = [];
28
37
  this.iconPosition = "left" /* IconPosition.Left */;
38
+ // Link properties (inherited from LinkMixin)
29
39
  this.href = EMPTY_STRING;
30
40
  this.target = EMPTY_STRING;
41
+ // Ripple property (inherited from RippleMixin)
31
42
  this.ripple = true;
43
+ // Accessibility properties
44
+ this.buttonAriaLabel = EMPTY_STRING;
45
+ this.ariaDescribedBy = EMPTY_STRING;
46
+ this.htmlType = EMPTY_STRING;
32
47
  /**
33
48
  * Required components that must be registered for this component to work properly
34
- * Can be overridden by parent implementations
35
49
  */
36
50
  this.requiredComponents = ['hy-icon'];
37
- this.buttonAriaLabel = EMPTY_STRING;
38
- this.ariaDescribedBy = EMPTY_STRING;
39
- this.htmlType = EMPTY_STRING;
40
51
  }
41
52
  /**
42
53
  * Check for required dependencies when component is connected to DOM
@@ -46,44 +57,22 @@ let NrButtonElement = class NrButtonElement extends NuralyUIBaseMixin(LitElement
46
57
  this.validateDependencies();
47
58
  }
48
59
  /**
49
- * Get the appropriate element tag based on button type
50
- */
51
- getElementTag() {
52
- return this.type === "link" /* ButtonType.Link */ && this.href ? 'a' : 'button';
53
- }
54
- /**
55
- * Get attributes for accessibility and functionality
60
+ * Get common attributes for both button and anchor elements
56
61
  */
57
- getElementAttributes() {
58
- const attributes = {
59
- '?disabled': this.disabled && this.type !== "link" /* ButtonType.Link */,
62
+ getCommonAttributes() {
63
+ return {
60
64
  'data-type': this.type,
61
65
  'data-shape': this.shape,
62
- 'data-size': this.size ? this.size : nothing,
66
+ 'data-size': this.size || nothing,
63
67
  'data-state': this.loading ? 'loading' : nothing,
64
68
  'data-theme': this.currentTheme,
65
69
  'data-block': this.block ? 'true' : nothing,
66
70
  'class': this.dashed ? 'button-dashed' : '',
67
- 'role': this.type === "link" /* ButtonType.Link */ ? 'link' : 'button',
68
71
  'aria-disabled': this.disabled ? 'true' : 'false',
69
72
  'aria-label': this.buttonAriaLabel || nothing,
70
73
  'aria-describedby': this.ariaDescribedBy || nothing,
74
+ 'tabindex': this.disabled ? '-1' : '0'
71
75
  };
72
- // Add link-specific attributes
73
- if (this.type === "link" /* ButtonType.Link */ && this.href) {
74
- attributes.href = this.href;
75
- if (this.target) {
76
- attributes.target = this.target;
77
- }
78
- if (this.target === '_blank') {
79
- attributes.rel = 'noopener noreferrer';
80
- }
81
- }
82
- // Add button-specific attributes
83
- if (this.type !== "link" /* ButtonType.Link */) {
84
- attributes.type = this.htmlType || 'button';
85
- }
86
- return attributes;
87
76
  }
88
77
  /**
89
78
  * Renders an icon if the hy-icon component is available
@@ -99,90 +88,89 @@ let NrButtonElement = class NrButtonElement extends NuralyUIBaseMixin(LitElement
99
88
  return html `<hy-icon name=${iconName}></hy-icon>`;
100
89
  }
101
90
  /**
102
- * Creates ripple effect on button click
103
- * @param event - The click event
104
- */
105
- createRipple(event) {
106
- if (!this.ripple || this.disabled)
107
- return;
108
- const button = event.currentTarget;
109
- const rect = button.getBoundingClientRect();
110
- const size = Math.max(rect.width, rect.height);
111
- const x = event.clientX - rect.left - size / 2;
112
- const y = event.clientY - rect.top - size / 2;
113
- const ripple = document.createElement('span');
114
- ripple.className = 'ripple';
115
- ripple.style.width = ripple.style.height = size + 'px';
116
- ripple.style.left = x + 'px';
117
- ripple.style.top = y + 'px';
118
- // Remove any existing ripples
119
- const existingRipples = button.querySelectorAll('.ripple');
120
- existingRipples.forEach(r => r.remove());
121
- button.appendChild(ripple);
122
- // Remove ripple after animation
123
- setTimeout(() => {
124
- ripple.remove();
125
- }, 600);
126
- }
127
- /**
128
- * Handle click events with ripple effect
129
- * @param event - The click event
91
+ * Handle comprehensive click events with proper event dispatching
130
92
  */
131
93
  handleClick(event) {
132
- this.createRipple(event);
94
+ if (this.disabled) {
95
+ event.preventDefault();
96
+ return;
97
+ }
98
+ // Use RippleMixin method
99
+ this.handleRippleClick(event);
100
+ // Handle link navigation if it's a link type
101
+ if (this.isLinkType()) {
102
+ this.dispatchCustomEvent('link-navigation', {
103
+ href: this.href,
104
+ target: this.target,
105
+ timestamp: Date.now(),
106
+ originalEvent: event
107
+ });
108
+ }
109
+ // Dispatch button event with metadata using EventHandlerMixin
110
+ this.dispatchEventWithMetadata('button-clicked', {
111
+ type: this.type,
112
+ disabled: this.disabled,
113
+ loading: this.loading,
114
+ href: this.href || null
115
+ });
133
116
  }
134
117
  render() {
135
- var _a, _b, _c, _d;
136
- const elementTag = this.getElementTag();
137
- const attributes = this.getElementAttributes();
118
+ var _a, _b;
119
+ const elementTag = this.getElementTag(); // From LinkMixin
120
+ const commonAttributes = this.getCommonAttributes();
121
+ const linkAttributes = this.getLinkAttributes(); // From LinkMixin
122
+ const content = html `
123
+ <span id="container">
124
+ ${((_a = this.icon) === null || _a === void 0 ? void 0 : _a.length) ? this.renderIcon(this.icon[0]) : nothing}
125
+ <slot id="slot"></slot>
126
+ ${((_b = this.icon) === null || _b === void 0 ? void 0 : _b.length) === 2 ? this.renderIcon(this.icon[1]) : nothing}
127
+ </span>
128
+ `;
138
129
  if (elementTag === 'a') {
139
130
  return html `
140
131
  <a
141
- href="${attributes.href}"
142
- target="${attributes.target || nothing}"
143
- rel="${attributes.rel || nothing}"
144
- data-type="${attributes['data-type']}"
145
- data-shape="${attributes['data-shape']}"
146
- data-size="${attributes['data-size']}"
147
- data-state="${attributes['data-state']}"
148
- data-theme="${attributes['data-theme']}"
149
- data-block="${attributes['data-block']}"
150
- class="${attributes.class}"
151
- role="${attributes.role}"
152
- aria-disabled="${attributes['aria-disabled']}"
153
- aria-label="${attributes['aria-label']}"
154
- aria-describedby="${attributes['aria-describedby']}"
132
+ href="${linkAttributes.href}"
133
+ target="${linkAttributes.target || nothing}"
134
+ rel="${linkAttributes.rel || nothing}"
135
+ role="${linkAttributes.role}"
136
+ data-type="${commonAttributes['data-type']}"
137
+ data-shape="${commonAttributes['data-shape']}"
138
+ data-size="${commonAttributes['data-size']}"
139
+ data-state="${commonAttributes['data-state']}"
140
+ data-theme="${commonAttributes['data-theme']}"
141
+ data-block="${commonAttributes['data-block']}"
142
+ class="${commonAttributes.class}"
143
+ aria-disabled="${this.disabled}"
144
+ aria-label="${this.buttonAriaLabel || nothing}"
145
+ aria-describedby="${this.ariaDescribedBy || nothing}"
146
+ tabindex="${this.disabled ? -1 : 0}"
147
+ @click="${this.handleClick}"
148
+ @keydown="${this.handleKeydown}"
155
149
  >
156
- <span id="container">
157
- ${((_a = this.icon) === null || _a === void 0 ? void 0 : _a.length) ? this.renderIcon(this.icon[0]) : nothing}
158
- <slot id="slot"></slot>
159
- ${((_b = this.icon) === null || _b === void 0 ? void 0 : _b.length) == 2 ? this.renderIcon(this.icon[1]) : nothing}
160
- </span>
150
+ ${content}
161
151
  </a>
162
152
  `;
163
153
  }
164
154
  return html `
165
155
  <button
166
- ?disabled="${attributes['?disabled']}"
167
- type="${attributes.type || nothing}"
168
- data-type="${attributes['data-type']}"
169
- data-shape="${attributes['data-shape']}"
170
- data-size="${attributes['data-size']}"
171
- data-state="${attributes['data-state']}"
172
- data-theme="${attributes['data-theme']}"
173
- data-block="${attributes['data-block']}"
174
- class="${attributes.class}"
175
- role="${attributes.role}"
176
- aria-disabled="${attributes['aria-disabled']}"
177
- aria-label="${attributes['aria-label']}"
178
- aria-describedby="${attributes['aria-describedby']}"
156
+ ?disabled="${this.disabled}"
157
+ type="${(this.htmlType || 'button')}"
158
+ role="${linkAttributes.role}"
159
+ data-type="${commonAttributes['data-type']}"
160
+ data-shape="${commonAttributes['data-shape']}"
161
+ data-size="${commonAttributes['data-size']}"
162
+ data-state="${commonAttributes['data-state']}"
163
+ data-theme="${commonAttributes['data-theme']}"
164
+ data-block="${commonAttributes['data-block']}"
165
+ class="${commonAttributes.class}"
166
+ aria-disabled="${this.disabled}"
167
+ aria-label="${this.buttonAriaLabel || nothing}"
168
+ aria-describedby="${this.ariaDescribedBy || nothing}"
169
+ tabindex="${this.disabled ? -1 : 0}"
179
170
  @click="${this.handleClick}"
171
+ @keydown="${this.handleKeydown}"
180
172
  >
181
- <span id="container">
182
- ${((_c = this.icon) === null || _c === void 0 ? void 0 : _c.length) ? this.renderIcon(this.icon[0]) : nothing}
183
- <slot id="slot"></slot>
184
- ${((_d = this.icon) === null || _d === void 0 ? void 0 : _d.length) == 2 ? this.renderIcon(this.icon[1]) : nothing}
185
- </span>
173
+ ${content}
186
174
  </button>
187
175
  `;
188
176
  }
@@ -1 +1 @@
1
- {"version":3,"file":"button.component.js","sourceRoot":"","sources":["../../../src/components/button/button.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { html, LitElement, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { ButtonType, ButtonShape, EMPTY_STRING, IconPosition } from './button.types.js';\nimport { styles } from './button.style.js';\nimport { NuralyUIBaseMixin } from '../../shared/base-mixin.js';\n\n@customElement('nr-button')\nexport class NrButtonElement extends NuralyUIBaseMixin(LitElement) {\n @property({type: Boolean})\n disabled = false;\n\n @property({type: Boolean})\n loading = false;\n\n @property({type: String})\n size = EMPTY_STRING;\n\n @property({type: String})\n type: ButtonType = ButtonType.Default;\n\n @property({type: String})\n shape: ButtonShape = ButtonShape.Default;\n\n @property({type: Boolean})\n block = false;\n\n @property({type: Boolean})\n dashed = false;\n\n @property({type: Array})\n icon: string[] = [];\n\n @property({reflect: true})\n iconPosition = IconPosition.Left;\n\n @property({type: String})\n href = EMPTY_STRING;\n\n @property({type: String})\n target = EMPTY_STRING;\n\n @property({type: Boolean})\n ripple = true;\n\n /**\n * Required components that must be registered for this component to work properly\n * Can be overridden by parent implementations\n */\n override requiredComponents = ['hy-icon'];\n\n /**\n * Check for required dependencies when component is connected to DOM\n */\n override connectedCallback() {\n super.connectedCallback();\n this.validateDependencies();\n }\n\n /**\n * Get the appropriate element tag based on button type\n */\n private getElementTag() {\n return this.type === ButtonType.Link && this.href ? 'a' : 'button';\n }\n\n /**\n * Get attributes for accessibility and functionality\n */\n private getElementAttributes() {\n const attributes: any = {\n '?disabled': this.disabled && this.type !== ButtonType.Link,\n 'data-type': this.type,\n 'data-shape': this.shape,\n 'data-size': this.size ? this.size : nothing,\n 'data-state': this.loading ? 'loading' : nothing,\n 'data-theme': this.currentTheme,\n 'data-block': this.block ? 'true' : nothing,\n 'class': this.dashed ? 'button-dashed' : '',\n 'role': this.type === ButtonType.Link ? 'link' : 'button',\n 'aria-disabled': this.disabled ? 'true' : 'false',\n 'aria-label': this.buttonAriaLabel || nothing,\n 'aria-describedby': this.ariaDescribedBy || nothing,\n };\n\n // Add link-specific attributes\n if (this.type === ButtonType.Link && this.href) {\n attributes.href = this.href;\n if (this.target) {\n attributes.target = this.target;\n }\n if (this.target === '_blank') {\n attributes.rel = 'noopener noreferrer';\n }\n }\n\n // Add button-specific attributes\n if (this.type !== ButtonType.Link) {\n attributes.type = this.htmlType || 'button';\n }\n\n return attributes;\n }\n\n @property({type: String})\n buttonAriaLabel = EMPTY_STRING;\n\n @property({type: String})\n ariaDescribedBy = EMPTY_STRING;\n\n @property({type: String})\n htmlType = EMPTY_STRING;\n\n /**\n * Renders an icon if the hy-icon component is available\n * @param iconName - The name of the icon to render\n * @returns TemplateResult or nothing\n */\n private renderIcon(iconName: string) {\n if (!this.isComponentAvailable('hy-icon')) {\n console.warn(\n `hy-icon component not found. Icon \"${iconName}\" will not be displayed. ` +\n `Please import hy-icon component.`\n );\n return nothing;\n }\n return html`<hy-icon name=${iconName}></hy-icon>`;\n }\n\n /**\n * Creates ripple effect on button click\n * @param event - The click event\n */\n private createRipple(event: MouseEvent) {\n if (!this.ripple || this.disabled) return;\n\n const button = event.currentTarget as HTMLElement;\n const rect = button.getBoundingClientRect();\n const size = Math.max(rect.width, rect.height);\n const x = event.clientX - rect.left - size / 2;\n const y = event.clientY - rect.top - size / 2;\n\n const ripple = document.createElement('span');\n ripple.className = 'ripple';\n ripple.style.width = ripple.style.height = size + 'px';\n ripple.style.left = x + 'px';\n ripple.style.top = y + 'px';\n\n // Remove any existing ripples\n const existingRipples = button.querySelectorAll('.ripple');\n existingRipples.forEach(r => r.remove());\n\n button.appendChild(ripple);\n\n // Remove ripple after animation\n setTimeout(() => {\n ripple.remove();\n }, 600);\n }\n\n /**\n * Handle click events with ripple effect\n * @param event - The click event\n */\n private handleClick(event: MouseEvent) {\n this.createRipple(event);\n }\n\n override render() {\n const elementTag = this.getElementTag();\n const attributes = this.getElementAttributes();\n \n if (elementTag === 'a') {\n return html`\n <a\n href=\"${attributes.href}\"\n target=\"${attributes.target || nothing}\"\n rel=\"${attributes.rel || nothing}\"\n data-type=\"${attributes['data-type']}\"\n data-shape=\"${attributes['data-shape']}\"\n data-size=\"${attributes['data-size']}\"\n data-state=\"${attributes['data-state']}\"\n data-theme=\"${attributes['data-theme']}\"\n data-block=\"${attributes['data-block']}\"\n class=\"${attributes.class}\"\n role=\"${attributes.role}\"\n aria-disabled=\"${attributes['aria-disabled']}\"\n aria-label=\"${attributes['aria-label']}\"\n aria-describedby=\"${attributes['aria-describedby']}\"\n >\n <span id=\"container\">\n ${this.icon?.length ? this.renderIcon(this.icon[0]) : nothing}\n <slot id=\"slot\"></slot>\n ${this.icon?.length == 2 ? this.renderIcon(this.icon[1]) : nothing}\n </span>\n </a>\n `;\n }\n \n return html`\n <button\n ?disabled=\"${attributes['?disabled']}\"\n type=\"${attributes.type || nothing}\"\n data-type=\"${attributes['data-type']}\"\n data-shape=\"${attributes['data-shape']}\"\n data-size=\"${attributes['data-size']}\"\n data-state=\"${attributes['data-state']}\"\n data-theme=\"${attributes['data-theme']}\"\n data-block=\"${attributes['data-block']}\"\n class=\"${attributes.class}\"\n role=\"${attributes.role}\"\n aria-disabled=\"${attributes['aria-disabled']}\"\n aria-label=\"${attributes['aria-label']}\"\n aria-describedby=\"${attributes['aria-describedby']}\"\n @click=\"${this.handleClick}\"\n >\n <span id=\"container\">\n ${this.icon?.length ? this.renderIcon(this.icon[0]) : nothing}\n <slot id=\"slot\"></slot>\n ${this.icon?.length == 2 ? this.renderIcon(this.icon[1]) : nothing}\n </span>\n </button>\n `;\n }\n static override styles = styles;\n}\n"]}
1
+ {"version":3,"file":"button.component.js","sourceRoot":"","sources":["../../../src/components/button/button.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { html, LitElement, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { ButtonType, ButtonShape, EMPTY_STRING, IconPosition } from './button.types.js';\nimport { styles } from './button.style.js';\nimport { NuralyUIBaseMixin } from '../../shared/base-mixin.js';\nimport { RippleMixin, KeyboardMixin, LinkMixin } from './mixins/index.js';\n\n/**\n * - NuralyUIBaseMixin: Core functionality (theme, dependencies, events)\n * - RippleMixin: Ripple effect handling\n * - KeyboardMixin: Keyboard interaction (Enter/Space activation)\n * - LinkMixin: Link-specific behavior for ButtonType.Link\n */\n@customElement('nr-button')\nexport class NrButtonElement extends RippleMixin(\n KeyboardMixin(\n LinkMixin(\n NuralyUIBaseMixin(LitElement)\n )\n )\n) {\n // Button state properties\n @property({ type: Boolean })\n override disabled = false;\n\n @property({ type: Boolean })\n loading = false;\n\n @property({ type: String })\n size = EMPTY_STRING;\n\n @property({ type: String })\n override type: ButtonType = ButtonType.Default;\n\n @property({ type: String })\n shape: ButtonShape = ButtonShape.Default;\n\n @property({ type: Boolean })\n block = false;\n\n @property({ type: Boolean })\n dashed = false;\n\n // Icon properties\n @property({ type: Array })\n icon: string[] = [];\n\n @property({ reflect: true })\n iconPosition = IconPosition.Left;\n\n // Link properties (inherited from LinkMixin)\n @property({ type: String })\n override href = EMPTY_STRING;\n\n @property({ type: String })\n override target = EMPTY_STRING;\n\n // Ripple property (inherited from RippleMixin)\n @property({ type: Boolean })\n override ripple = true;\n\n // Accessibility properties\n @property({ type: String })\n buttonAriaLabel = EMPTY_STRING;\n\n @property({ type: String })\n ariaDescribedBy = EMPTY_STRING;\n\n @property({ type: String })\n htmlType = EMPTY_STRING;\n\n /**\n * Required components that must be registered for this component to work properly\n */\n override requiredComponents = ['hy-icon'];\n\n /**\n * Check for required dependencies when component is connected to DOM\n */\n override connectedCallback() {\n super.connectedCallback();\n this.validateDependencies();\n }\n\n /**\n * Get common attributes for both button and anchor elements\n */\n private getCommonAttributes() {\n return {\n 'data-type': this.type,\n 'data-shape': this.shape,\n 'data-size': this.size || nothing,\n 'data-state': this.loading ? 'loading' : nothing,\n 'data-theme': this.currentTheme,\n 'data-block': this.block ? 'true' : nothing,\n 'class': this.dashed ? 'button-dashed' : '',\n 'aria-disabled': this.disabled ? 'true' : 'false',\n 'aria-label': this.buttonAriaLabel || nothing,\n 'aria-describedby': this.ariaDescribedBy || nothing,\n 'tabindex': this.disabled ? '-1' : '0'\n };\n }\n\n /**\n * Renders an icon if the hy-icon component is available\n * @param iconName - The name of the icon to render\n * @returns TemplateResult or nothing\n */\n private renderIcon(iconName: string) {\n if (!this.isComponentAvailable('hy-icon')) {\n console.warn(\n `hy-icon component not found. Icon \"${iconName}\" will not be displayed. ` +\n `Please import hy-icon component.`\n );\n return nothing;\n }\n return html`<hy-icon name=${iconName}></hy-icon>`;\n }\n\n /**\n * Handle comprehensive click events with proper event dispatching\n */\n private handleClick(event: MouseEvent) {\n if (this.disabled) {\n event.preventDefault();\n return;\n }\n\n // Use RippleMixin method\n this.handleRippleClick(event);\n \n // Handle link navigation if it's a link type\n if (this.isLinkType()) {\n this.dispatchCustomEvent('link-navigation', {\n href: this.href,\n target: this.target,\n timestamp: Date.now(),\n originalEvent: event\n });\n }\n \n // Dispatch button event with metadata using EventHandlerMixin\n this.dispatchEventWithMetadata('button-clicked', {\n type: this.type,\n disabled: this.disabled,\n loading: this.loading,\n href: this.href || null\n });\n }\n\n override render() {\n const elementTag = this.getElementTag(); // From LinkMixin\n const commonAttributes = this.getCommonAttributes();\n const linkAttributes = this.getLinkAttributes(); // From LinkMixin\n \n const content = html`\n <span id=\"container\">\n ${this.icon?.length ? this.renderIcon(this.icon[0]) : nothing}\n <slot id=\"slot\"></slot>\n ${this.icon?.length === 2 ? this.renderIcon(this.icon[1]) : nothing}\n </span>\n `;\n \n if (elementTag === 'a') {\n return html`\n <a\n href=\"${linkAttributes.href}\"\n target=\"${linkAttributes.target || nothing}\"\n rel=\"${linkAttributes.rel || nothing}\"\n role=\"${linkAttributes.role}\"\n data-type=\"${commonAttributes['data-type']}\"\n data-shape=\"${commonAttributes['data-shape']}\"\n data-size=\"${commonAttributes['data-size']}\"\n data-state=\"${commonAttributes['data-state']}\"\n data-theme=\"${commonAttributes['data-theme']}\"\n data-block=\"${commonAttributes['data-block']}\"\n class=\"${commonAttributes.class}\"\n aria-disabled=\"${this.disabled}\"\n aria-label=\"${this.buttonAriaLabel || nothing}\"\n aria-describedby=\"${this.ariaDescribedBy || nothing}\"\n tabindex=\"${this.disabled ? -1 : 0}\"\n @click=\"${this.handleClick}\"\n @keydown=\"${this.handleKeydown}\"\n >\n ${content}\n </a>\n `;\n }\n \n return html`\n <button\n ?disabled=\"${this.disabled}\"\n type=\"${(this.htmlType || 'button') as 'button' | 'submit' | 'reset'}\"\n role=\"${linkAttributes.role}\"\n data-type=\"${commonAttributes['data-type']}\"\n data-shape=\"${commonAttributes['data-shape']}\"\n data-size=\"${commonAttributes['data-size']}\" \n data-state=\"${commonAttributes['data-state']}\"\n data-theme=\"${commonAttributes['data-theme']}\"\n data-block=\"${commonAttributes['data-block']}\"\n class=\"${commonAttributes.class}\"\n aria-disabled=\"${this.disabled}\"\n aria-label=\"${this.buttonAriaLabel || nothing}\"\n aria-describedby=\"${this.ariaDescribedBy || nothing}\"\n tabindex=\"${this.disabled ? -1 : 0}\"\n @click=\"${this.handleClick}\"\n @keydown=\"${this.handleKeydown}\"\n >\n ${content}\n </button>\n `;\n }\n static override styles = styles;\n}\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ export { RippleMixin, type RippleCapable } from './ripple-mixin.js';
7
+ export { KeyboardMixin, type KeyboardCapable } from './keyboard-mixin.js';
8
+ export { LinkMixin, type LinkCapable } from './link-mixin.js';
9
+ import type { RippleCapable } from './ripple-mixin.js';
10
+ import type { KeyboardCapable } from './keyboard-mixin.js';
11
+ import type { LinkCapable } from './link-mixin.js';
12
+ export interface ButtonMixinCapable extends RippleCapable, KeyboardCapable, LinkCapable {
13
+ }
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/button/mixins/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,MAAM,WAAW,kBAAmB,SAAQ,aAAa,EAAE,eAAe,EAAE,WAAW;CAAG"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ // Export all button-specific mixins
7
+ export { RippleMixin } from './ripple-mixin.js';
8
+ export { KeyboardMixin } from './keyboard-mixin.js';
9
+ export { LinkMixin } from './link-mixin.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/button/mixins/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oCAAoC;AACpC,OAAO,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAoB,MAAM,iBAAiB,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\n// Export all button-specific mixins\nexport { RippleMixin, type RippleCapable } from './ripple-mixin.js';\nexport { KeyboardMixin, type KeyboardCapable } from './keyboard-mixin.js';\nexport { LinkMixin, type LinkCapable } from './link-mixin.js';\n\n// Import types for combined interface\nimport type { RippleCapable } from './ripple-mixin.js';\nimport type { KeyboardCapable } from './keyboard-mixin.js';\nimport type { LinkCapable } from './link-mixin.js';\n\n// Combined interface for button components using all mixins\nexport interface ButtonMixinCapable extends RippleCapable, KeyboardCapable, LinkCapable {}\n"]}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { LitElement } from 'lit';
7
+ declare type Constructor<T = {}> = new (...args: any[]) => T;
8
+ /**
9
+ * Interface for components that support keyboard interaction
10
+ */
11
+ export interface KeyboardCapable {
12
+ /**
13
+ * Whether the component is disabled
14
+ */
15
+ disabled: boolean;
16
+ /**
17
+ * Handle keyboard activation (Enter/Space)
18
+ */
19
+ handleKeyboardActivation(event: KeyboardEvent): void;
20
+ /**
21
+ * Handle keydown events with proper focus management
22
+ */
23
+ handleKeydown(event: KeyboardEvent): void;
24
+ }
25
+ /**
26
+ * Mixin that provides keyboard interaction capabilities for button-like components
27
+ * Handles Enter and Space key activation following ARIA best practices
28
+ *
29
+ * @param superClass - The base class to extend
30
+ * @returns Enhanced class with keyboard interaction capabilities
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * export class MyButton extends KeyboardMixin(LitElement) {
35
+ * @property({ type: Boolean }) disabled = false;
36
+ *
37
+ * render() {
38
+ * return html`
39
+ * <button
40
+ * @keydown="${this.handleKeydown}"
41
+ * tabindex="${this.disabled ? '-1' : '0'}"
42
+ * >
43
+ * <slot></slot>
44
+ * </button>
45
+ * `;
46
+ * }
47
+ * }
48
+ * ```
49
+ */
50
+ export declare const KeyboardMixin: <T extends Constructor<LitElement>>(superClass: T) => Constructor<KeyboardCapable> & T;
51
+ export {};
52
+ //# sourceMappingURL=keyboard-mixin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard-mixin.d.ts","sourceRoot":"","sources":["../../../../src/components/button/mixins/keyboard-mixin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEjC,aAAK,WAAW,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,wBAAwB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,aAAa,wFAwDzB,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Mixin that provides keyboard interaction capabilities for button-like components
8
+ * Handles Enter and Space key activation following ARIA best practices
9
+ *
10
+ * @param superClass - The base class to extend
11
+ * @returns Enhanced class with keyboard interaction capabilities
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * export class MyButton extends KeyboardMixin(LitElement) {
16
+ * @property({ type: Boolean }) disabled = false;
17
+ *
18
+ * render() {
19
+ * return html`
20
+ * <button
21
+ * @keydown="${this.handleKeydown}"
22
+ * tabindex="${this.disabled ? '-1' : '0'}"
23
+ * >
24
+ * <slot></slot>
25
+ * </button>
26
+ * `;
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ export const KeyboardMixin = (superClass) => {
32
+ class KeyboardMixinClass extends superClass {
33
+ /**
34
+ * Handle keyboard activation (Enter/Space keys)
35
+ * @param event - The keyboard event
36
+ */
37
+ handleKeyboardActivation(event) {
38
+ if (this.disabled)
39
+ return;
40
+ // Check if EventHandlerMixin is available for proper key checking
41
+ const isActivationKey = typeof this.isActivationKey === 'function'
42
+ ? this.isActivationKey(event)
43
+ : (event.key === 'Enter' || event.key === ' ');
44
+ if (isActivationKey) {
45
+ event.preventDefault();
46
+ // Trigger click event for consistency
47
+ this.click();
48
+ // Dispatch custom keyboard activation event if EventHandling mixin is available
49
+ if (typeof this.dispatchCustomEvent === 'function') {
50
+ this.dispatchCustomEvent('keyboard-activation', {
51
+ key: event.key,
52
+ timestamp: Date.now(),
53
+ target: this
54
+ });
55
+ }
56
+ }
57
+ }
58
+ /**
59
+ * Handle keydown events with proper disabled state checking
60
+ * @param event - The keyboard event
61
+ */
62
+ handleKeydown(event) {
63
+ if (this.disabled) {
64
+ // Allow readonly navigation keys even when disabled
65
+ const isNavigationKey = typeof this.isReadonlyKeyAllowed === 'function'
66
+ ? this.isReadonlyKeyAllowed(event)
67
+ : ['Tab', 'Shift', 'Escape', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key);
68
+ if (!isNavigationKey) {
69
+ event.preventDefault();
70
+ return;
71
+ }
72
+ }
73
+ this.handleKeyboardActivation(event);
74
+ }
75
+ }
76
+ return KeyboardMixinClass;
77
+ };
78
+ //# sourceMappingURL=keyboard-mixin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard-mixin.js","sourceRoot":"","sources":["../../../../src/components/button/mixins/keyboard-mixin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0BH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAoC,UAAa,EAAE,EAAE;IAChF,MAAM,kBAAmB,SAAQ,UAAU;QAIzC;;;WAGG;QACH,wBAAwB,CAAC,KAAoB;YAC3C,IAAI,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAE1B,kEAAkE;YAClE,MAAM,eAAe,GAAG,OAAQ,IAAY,CAAC,eAAe,KAAK,UAAU;gBACzE,CAAC,CAAE,IAAY,CAAC,eAAe,CAAC,KAAK,CAAC;gBACtC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YAEjD,IAAI,eAAe,EAAE;gBACnB,KAAK,CAAC,cAAc,EAAE,CAAC;gBAEvB,sCAAsC;gBACtC,IAAI,CAAC,KAAK,EAAE,CAAC;gBAEb,gFAAgF;gBAChF,IAAI,OAAQ,IAAY,CAAC,mBAAmB,KAAK,UAAU,EAAE;oBAC1D,IAAY,CAAC,mBAAmB,CAAC,qBAAqB,EAAE;wBACvD,GAAG,EAAE,KAAK,CAAC,GAAG;wBACd,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;wBACrB,MAAM,EAAE,IAAI;qBACb,CAAC,CAAC;iBACJ;aACF;QACH,CAAC;QAED;;;WAGG;QACH,aAAa,CAAC,KAAoB;YAChC,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,oDAAoD;gBACpD,MAAM,eAAe,GAAG,OAAQ,IAAY,CAAC,oBAAoB,KAAK,UAAU;oBAC9E,CAAC,CAAE,IAAY,CAAC,oBAAoB,CAAC,KAAK,CAAC;oBAC3C,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAErH,IAAI,CAAC,eAAe,EAAE;oBACpB,KAAK,CAAC,cAAc,EAAE,CAAC;oBACvB,OAAO;iBACR;aACF;YAED,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACvC,CAAC;KACF;IAED,OAAO,kBAAsD,CAAC;AAChE,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { LitElement } from 'lit';\n\ntype Constructor<T = {}> = new (...args: any[]) => T;\n\n/**\n * Interface for components that support keyboard interaction\n */\nexport interface KeyboardCapable {\n /**\n * Whether the component is disabled\n */\n disabled: boolean;\n \n /**\n * Handle keyboard activation (Enter/Space)\n */\n handleKeyboardActivation(event: KeyboardEvent): void;\n \n /**\n * Handle keydown events with proper focus management\n */\n handleKeydown(event: KeyboardEvent): void;\n}\n\n/**\n * Mixin that provides keyboard interaction capabilities for button-like components\n * Handles Enter and Space key activation following ARIA best practices\n * \n * @param superClass - The base class to extend\n * @returns Enhanced class with keyboard interaction capabilities\n * \n * @example\n * ```typescript\n * export class MyButton extends KeyboardMixin(LitElement) {\n * @property({ type: Boolean }) disabled = false;\n * \n * render() {\n * return html`\n * <button \n * @keydown=\"${this.handleKeydown}\"\n * tabindex=\"${this.disabled ? '-1' : '0'}\"\n * >\n * <slot></slot>\n * </button>\n * `;\n * }\n * }\n * ```\n */\nexport const KeyboardMixin = <T extends Constructor<LitElement>>(superClass: T) => {\n class KeyboardMixinClass extends superClass implements KeyboardCapable {\n \n declare disabled: boolean;\n \n /**\n * Handle keyboard activation (Enter/Space keys)\n * @param event - The keyboard event\n */\n handleKeyboardActivation(event: KeyboardEvent): void {\n if (this.disabled) return;\n \n // Check if EventHandlerMixin is available for proper key checking\n const isActivationKey = typeof (this as any).isActivationKey === 'function'\n ? (this as any).isActivationKey(event)\n : (event.key === 'Enter' || event.key === ' ');\n \n if (isActivationKey) {\n event.preventDefault();\n \n // Trigger click event for consistency\n this.click();\n \n // Dispatch custom keyboard activation event if EventHandling mixin is available\n if (typeof (this as any).dispatchCustomEvent === 'function') {\n (this as any).dispatchCustomEvent('keyboard-activation', {\n key: event.key,\n timestamp: Date.now(),\n target: this\n });\n }\n }\n }\n\n /**\n * Handle keydown events with proper disabled state checking\n * @param event - The keyboard event\n */\n handleKeydown(event: KeyboardEvent): void {\n if (this.disabled) {\n // Allow readonly navigation keys even when disabled\n const isNavigationKey = typeof (this as any).isReadonlyKeyAllowed === 'function'\n ? (this as any).isReadonlyKeyAllowed(event)\n : ['Tab', 'Shift', 'Escape', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key);\n \n if (!isNavigationKey) {\n event.preventDefault();\n return;\n }\n }\n \n this.handleKeyboardActivation(event);\n }\n }\n\n return KeyboardMixinClass as Constructor<KeyboardCapable> & T;\n};\n"]}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { LitElement } from 'lit';
7
+ import { ButtonType } from '../button.types.js';
8
+ declare type Constructor<T = {}> = new (...args: any[]) => T;
9
+ /**
10
+ * Interface for components that support link behavior
11
+ */
12
+ export interface LinkCapable {
13
+ /**
14
+ * Button type that determines if it should render as link
15
+ */
16
+ type: ButtonType;
17
+ /**
18
+ * URL for link buttons
19
+ */
20
+ href: string;
21
+ /**
22
+ * Target attribute for link buttons
23
+ */
24
+ target: string;
25
+ /**
26
+ * Get the appropriate element tag (button or a)
27
+ */
28
+ getElementTag(): string;
29
+ /**
30
+ * Get link-specific attributes
31
+ */
32
+ getLinkAttributes(): Record<string, any>;
33
+ /**
34
+ * Check if component should render as a link
35
+ */
36
+ isLinkType(): boolean;
37
+ }
38
+ /**
39
+ * Mixin that provides link behavior for button components
40
+ * Handles the distinction between button and anchor elements
41
+ *
42
+ * @param superClass - The base class to extend
43
+ * @returns Enhanced class with link capabilities
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * export class MyButton extends LinkMixin(LitElement) {
48
+ * @property({ type: String }) type = ButtonType.Default;
49
+ * @property({ type: String }) href = '';
50
+ * @property({ type: String }) target = '';
51
+ *
52
+ * render() {
53
+ * const tag = this.getElementTag();
54
+ * const attrs = this.getLinkAttributes();
55
+ *
56
+ * return html`
57
+ * <${tag} ...${attrs}>
58
+ * <slot></slot>
59
+ * </${tag}>
60
+ * `;
61
+ * }
62
+ * }
63
+ * ```
64
+ */
65
+ export declare const LinkMixin: <T extends Constructor<LitElement>>(superClass: T) => Constructor<LinkCapable> & T;
66
+ export {};
67
+ //# sourceMappingURL=link-mixin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-mixin.d.ts","sourceRoot":"","sources":["../../../../src/components/button/mixins/link-mixin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,aAAK,WAAW,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,IAAI,EAAE,UAAU,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,aAAa,IAAI,MAAM,CAAC;IAExB;;OAEG;IACH,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEzC;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,SAAS,oFAkErB,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Mixin that provides link behavior for button components
8
+ * Handles the distinction between button and anchor elements
9
+ *
10
+ * @param superClass - The base class to extend
11
+ * @returns Enhanced class with link capabilities
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * export class MyButton extends LinkMixin(LitElement) {
16
+ * @property({ type: String }) type = ButtonType.Default;
17
+ * @property({ type: String }) href = '';
18
+ * @property({ type: String }) target = '';
19
+ *
20
+ * render() {
21
+ * const tag = this.getElementTag();
22
+ * const attrs = this.getLinkAttributes();
23
+ *
24
+ * return html`
25
+ * <${tag} ...${attrs}>
26
+ * <slot></slot>
27
+ * </${tag}>
28
+ * `;
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ export const LinkMixin = (superClass) => {
34
+ class LinkMixinClass extends superClass {
35
+ /**
36
+ * Check if the button should render as a link
37
+ */
38
+ isLinkType() {
39
+ return this.type === "link" /* ButtonType.Link */ && !!this.href;
40
+ }
41
+ /**
42
+ * Get the appropriate element tag based on button type
43
+ */
44
+ getElementTag() {
45
+ return this.isLinkType() ? 'a' : 'button';
46
+ }
47
+ /**
48
+ * Get link-specific attributes for anchor elements
49
+ */
50
+ getLinkAttributes() {
51
+ const attributes = {};
52
+ if (this.isLinkType()) {
53
+ attributes.href = this.href;
54
+ if (this.target) {
55
+ attributes.target = this.target;
56
+ // Add security attributes for external links
57
+ if (this.target === '_blank') {
58
+ attributes.rel = 'noopener noreferrer';
59
+ }
60
+ }
61
+ attributes.role = 'link';
62
+ }
63
+ else {
64
+ attributes.role = 'button';
65
+ }
66
+ return attributes;
67
+ }
68
+ /**
69
+ * Handle link navigation with proper event dispatching
70
+ */
71
+ handleLinkNavigation(event) {
72
+ if (this.isLinkType()) {
73
+ // Dispatch custom navigation event if EventHandling mixin is available
74
+ if (typeof this.dispatchCustomEvent === 'function') {
75
+ this.dispatchCustomEvent('link-navigation', {
76
+ href: this.href,
77
+ target: this.target,
78
+ timestamp: Date.now(),
79
+ originalEvent: event
80
+ });
81
+ }
82
+ }
83
+ }
84
+ }
85
+ return LinkMixinClass;
86
+ };
87
+ //# sourceMappingURL=link-mixin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-mixin.js","sourceRoot":"","sources":["../../../../src/components/button/mixins/link-mixin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0CH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAoC,UAAa,EAAE,EAAE;IAC5E,MAAM,cAAe,SAAQ,UAAU;QAMrC;;WAEG;QACH,UAAU;YACR,OAAO,IAAI,CAAC,IAAI,iCAAoB,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACtD,CAAC;QAED;;WAEG;QACH,aAAa;YACX,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC5C,CAAC;QAED;;WAEG;QACH,iBAAiB;YACf,MAAM,UAAU,GAAwB,EAAE,CAAC;YAE3C,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;gBACrB,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;gBAE5B,IAAI,IAAI,CAAC,MAAM,EAAE;oBACf,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;oBAEhC,6CAA6C;oBAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE;wBAC5B,UAAU,CAAC,GAAG,GAAG,qBAAqB,CAAC;qBACxC;iBACF;gBAED,UAAU,CAAC,IAAI,GAAG,MAAM,CAAC;aAC1B;iBAAM;gBACL,UAAU,CAAC,IAAI,GAAG,QAAQ,CAAC;aAC5B;YAED,OAAO,UAAU,CAAC;QACpB,CAAC;QAED;;WAEG;QACH,oBAAoB,CAAC,KAAY;YAC/B,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;gBACrB,uEAAuE;gBACvE,IAAI,OAAQ,IAAY,CAAC,mBAAmB,KAAK,UAAU,EAAE;oBAC1D,IAAY,CAAC,mBAAmB,CAAC,iBAAiB,EAAE;wBACnD,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,MAAM,EAAE,IAAI,CAAC,MAAM;wBACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;wBACrB,aAAa,EAAE,KAAK;qBACrB,CAAC,CAAC;iBACJ;aACF;QACH,CAAC;KACF;IAED,OAAO,cAA8C,CAAC;AACxD,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { LitElement } from 'lit';\nimport { ButtonType } from '../button.types.js';\n\ntype Constructor<T = {}> = new (...args: any[]) => T;\n\n/**\n * Interface for components that support link behavior\n */\nexport interface LinkCapable {\n /**\n * Button type that determines if it should render as link\n */\n type: ButtonType;\n \n /**\n * URL for link buttons\n */\n href: string;\n \n /**\n * Target attribute for link buttons\n */\n target: string;\n \n /**\n * Get the appropriate element tag (button or a)\n */\n getElementTag(): string;\n \n /**\n * Get link-specific attributes\n */\n getLinkAttributes(): Record<string, any>;\n \n /**\n * Check if component should render as a link\n */\n isLinkType(): boolean;\n}\n\n/**\n * Mixin that provides link behavior for button components\n * Handles the distinction between button and anchor elements\n * \n * @param superClass - The base class to extend\n * @returns Enhanced class with link capabilities\n * \n * @example\n * ```typescript\n * export class MyButton extends LinkMixin(LitElement) {\n * @property({ type: String }) type = ButtonType.Default;\n * @property({ type: String }) href = '';\n * @property({ type: String }) target = '';\n * \n * render() {\n * const tag = this.getElementTag();\n * const attrs = this.getLinkAttributes();\n * \n * return html`\n * <${tag} ...${attrs}>\n * <slot></slot>\n * </${tag}>\n * `;\n * }\n * }\n * ```\n */\nexport const LinkMixin = <T extends Constructor<LitElement>>(superClass: T) => {\n class LinkMixinClass extends superClass implements LinkCapable {\n \n declare type: ButtonType;\n declare href: string;\n declare target: string;\n \n /**\n * Check if the button should render as a link\n */\n isLinkType(): boolean {\n return this.type === ButtonType.Link && !!this.href;\n }\n \n /**\n * Get the appropriate element tag based on button type\n */\n getElementTag(): string {\n return this.isLinkType() ? 'a' : 'button';\n }\n \n /**\n * Get link-specific attributes for anchor elements\n */\n getLinkAttributes(): Record<string, any> {\n const attributes: Record<string, any> = {};\n \n if (this.isLinkType()) {\n attributes.href = this.href;\n \n if (this.target) {\n attributes.target = this.target;\n \n // Add security attributes for external links\n if (this.target === '_blank') {\n attributes.rel = 'noopener noreferrer';\n }\n }\n \n attributes.role = 'link';\n } else {\n attributes.role = 'button';\n }\n \n return attributes;\n }\n \n /**\n * Handle link navigation with proper event dispatching\n */\n handleLinkNavigation(event: Event): void {\n if (this.isLinkType()) {\n // Dispatch custom navigation event if EventHandling mixin is available\n if (typeof (this as any).dispatchCustomEvent === 'function') {\n (this as any).dispatchCustomEvent('link-navigation', {\n href: this.href,\n target: this.target,\n timestamp: Date.now(),\n originalEvent: event\n });\n }\n }\n }\n }\n\n return LinkMixinClass as Constructor<LinkCapable> & T;\n};\n"]}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ import { LitElement } from 'lit';
7
+ declare type Constructor<T = {}> = new (...args: any[]) => T;
8
+ /**
9
+ * Interface for components that support ripple effect
10
+ */
11
+ export interface RippleCapable {
12
+ /**
13
+ * Whether ripple effect is enabled
14
+ */
15
+ ripple: boolean;
16
+ /**
17
+ * Whether the component is disabled (affects ripple)
18
+ */
19
+ disabled: boolean;
20
+ /**
21
+ * Create ripple effect at click position
22
+ */
23
+ createRipple(event: MouseEvent): void;
24
+ /**
25
+ * Handle click events with ripple effect
26
+ */
27
+ handleRippleClick(event: MouseEvent): void;
28
+ }
29
+ /**
30
+ * Mixin that provides ripple effect functionality for button-like components
31
+ *
32
+ * @param superClass - The base class to extend
33
+ * @returns Enhanced class with ripple effect capabilities
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * export class MyButton extends RippleMixin(LitElement) {
38
+ * @property({ type: Boolean }) ripple = true;
39
+ * @property({ type: Boolean }) disabled = false;
40
+ *
41
+ * render() {
42
+ * return html`
43
+ * <button @click="${this.handleRippleClick}">
44
+ * <slot></slot>
45
+ * </button>
46
+ * `;
47
+ * }
48
+ * }
49
+ * ```
50
+ */
51
+ export declare const RippleMixin: <T extends Constructor<LitElement>>(superClass: T) => Constructor<RippleCapable> & T;
52
+ export {};
53
+ //# sourceMappingURL=ripple-mixin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ripple-mixin.d.ts","sourceRoot":"","sources":["../../../../src/components/button/mixins/ripple-mixin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEjC,aAAK,WAAW,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAEtC;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,WAAW,sFA2DvB,CAAC"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ /**
7
+ * Mixin that provides ripple effect functionality for button-like components
8
+ *
9
+ * @param superClass - The base class to extend
10
+ * @returns Enhanced class with ripple effect capabilities
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * export class MyButton extends RippleMixin(LitElement) {
15
+ * @property({ type: Boolean }) ripple = true;
16
+ * @property({ type: Boolean }) disabled = false;
17
+ *
18
+ * render() {
19
+ * return html`
20
+ * <button @click="${this.handleRippleClick}">
21
+ * <slot></slot>
22
+ * </button>
23
+ * `;
24
+ * }
25
+ * }
26
+ * ```
27
+ */
28
+ export const RippleMixin = (superClass) => {
29
+ class RippleMixinClass extends superClass {
30
+ /**
31
+ * Creates ripple effect on button click
32
+ * @param event - The click event
33
+ */
34
+ createRipple(event) {
35
+ if (!this.ripple || this.disabled)
36
+ return;
37
+ const button = event.currentTarget;
38
+ const rect = button.getBoundingClientRect();
39
+ const size = Math.max(rect.width, rect.height);
40
+ const x = event.clientX - rect.left - size / 2;
41
+ const y = event.clientY - rect.top - size / 2;
42
+ const ripple = document.createElement('span');
43
+ ripple.className = 'ripple';
44
+ ripple.style.width = ripple.style.height = size + 'px';
45
+ ripple.style.left = x + 'px';
46
+ ripple.style.top = y + 'px';
47
+ // Remove any existing ripples
48
+ const existingRipples = button.querySelectorAll('.ripple');
49
+ existingRipples.forEach(r => r.remove());
50
+ button.appendChild(ripple);
51
+ // Remove ripple after animation
52
+ setTimeout(() => {
53
+ ripple.remove();
54
+ }, 600);
55
+ }
56
+ /**
57
+ * Handle click events with ripple effect and dispatch custom event
58
+ * @param event - The click event
59
+ */
60
+ handleRippleClick(event) {
61
+ this.createRipple(event);
62
+ // Dispatch custom button click event if EventHandling mixin is available
63
+ if (typeof this.dispatchCustomEvent === 'function') {
64
+ this.dispatchCustomEvent('button-click', {
65
+ disabled: this.disabled,
66
+ timestamp: Date.now(),
67
+ coordinates: {
68
+ x: event.clientX,
69
+ y: event.clientY
70
+ }
71
+ });
72
+ }
73
+ }
74
+ }
75
+ return RippleMixinClass;
76
+ };
77
+ //# sourceMappingURL=ripple-mixin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ripple-mixin.js","sourceRoot":"","sources":["../../../../src/components/button/mixins/ripple-mixin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA+BH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAoC,UAAa,EAAE,EAAE;IAC9E,MAAM,gBAAiB,SAAQ,UAAU;QAKvC;;;WAGG;QACH,YAAY,CAAC,KAAiB;YAC5B,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAE1C,MAAM,MAAM,GAAG,KAAK,CAAC,aAA4B,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC;YAE9C,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC9C,MAAM,CAAC,SAAS,GAAG,QAAQ,CAAC;YAC5B,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;YACvD,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;YAE5B,8BAA8B;YAC9B,MAAM,eAAe,GAAG,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC3D,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;YAEzC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAE3B,gCAAgC;YAChC,UAAU,CAAC,GAAG,EAAE;gBACd,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,CAAC,EAAE,GAAG,CAAC,CAAC;QACV,CAAC;QAED;;;WAGG;QACH,iBAAiB,CAAC,KAAiB;YACjC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAEzB,yEAAyE;YACzE,IAAI,OAAQ,IAAY,CAAC,mBAAmB,KAAK,UAAU,EAAE;gBAC1D,IAAY,CAAC,mBAAmB,CAAC,cAAc,EAAE;oBAChD,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;oBACrB,WAAW,EAAE;wBACX,CAAC,EAAE,KAAK,CAAC,OAAO;wBAChB,CAAC,EAAE,KAAK,CAAC,OAAO;qBACjB;iBACF,CAAC,CAAC;aACJ;QACH,CAAC;KACF;IAED,OAAO,gBAAkD,CAAC;AAC5D,CAAC,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Nuraly, Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { LitElement } from 'lit';\n\ntype Constructor<T = {}> = new (...args: any[]) => T;\n\n/**\n * Interface for components that support ripple effect\n */\nexport interface RippleCapable {\n /**\n * Whether ripple effect is enabled\n */\n ripple: boolean;\n \n /**\n * Whether the component is disabled (affects ripple)\n */\n disabled: boolean;\n \n /**\n * Create ripple effect at click position\n */\n createRipple(event: MouseEvent): void;\n \n /**\n * Handle click events with ripple effect\n */\n handleRippleClick(event: MouseEvent): void;\n}\n\n/**\n * Mixin that provides ripple effect functionality for button-like components\n * \n * @param superClass - The base class to extend\n * @returns Enhanced class with ripple effect capabilities\n * \n * @example\n * ```typescript\n * export class MyButton extends RippleMixin(LitElement) {\n * @property({ type: Boolean }) ripple = true;\n * @property({ type: Boolean }) disabled = false;\n * \n * render() {\n * return html`\n * <button @click=\"${this.handleRippleClick}\">\n * <slot></slot>\n * </button>\n * `;\n * }\n * }\n * ```\n */\nexport const RippleMixin = <T extends Constructor<LitElement>>(superClass: T) => {\n class RippleMixinClass extends superClass implements RippleCapable {\n \n declare ripple: boolean;\n declare disabled: boolean;\n \n /**\n * Creates ripple effect on button click\n * @param event - The click event\n */\n createRipple(event: MouseEvent): void {\n if (!this.ripple || this.disabled) return;\n\n const button = event.currentTarget as HTMLElement;\n const rect = button.getBoundingClientRect();\n const size = Math.max(rect.width, rect.height);\n const x = event.clientX - rect.left - size / 2;\n const y = event.clientY - rect.top - size / 2;\n\n const ripple = document.createElement('span');\n ripple.className = 'ripple';\n ripple.style.width = ripple.style.height = size + 'px';\n ripple.style.left = x + 'px';\n ripple.style.top = y + 'px';\n\n // Remove any existing ripples\n const existingRipples = button.querySelectorAll('.ripple');\n existingRipples.forEach(r => r.remove());\n\n button.appendChild(ripple);\n\n // Remove ripple after animation\n setTimeout(() => {\n ripple.remove();\n }, 600);\n }\n\n /**\n * Handle click events with ripple effect and dispatch custom event\n * @param event - The click event\n */\n handleRippleClick(event: MouseEvent): void {\n this.createRipple(event);\n \n // Dispatch custom button click event if EventHandling mixin is available\n if (typeof (this as any).dispatchCustomEvent === 'function') {\n (this as any).dispatchCustomEvent('button-click', {\n disabled: this.disabled,\n timestamp: Date.now(),\n coordinates: {\n x: event.clientX,\n y: event.clientY\n }\n });\n }\n }\n }\n\n return RippleMixinClass as Constructor<RippleCapable> & T;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuralyui/button",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "Button component for NuralyUI library",
5
5
  "main": "index.js",
6
6
  "type": "module",