@nuralyui/button 0.0.12 → 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.
- package/button.component.d.ts +57 -0
- package/button.component.d.ts.map +1 -0
- package/button.component.js +228 -0
- package/button.component.js.map +1 -0
- package/{nr-button.style.d.ts → button.style.d.ts} +1 -1
- package/button.style.d.ts.map +1 -0
- package/{nr-button.style.js → button.style.js} +180 -2
- package/button.style.js.map +1 -0
- package/{nr-button.style.variables.d.ts → button.style.variables.d.ts} +1 -1
- package/button.style.variables.d.ts.map +1 -0
- package/{nr-button.style.variables.js → button.style.variables.js} +1 -1
- package/button.style.variables.js.map +1 -0
- package/{nr-button.types.d.ts → button.types.d.ts} +9 -2
- package/button.types.d.ts.map +1 -0
- package/button.types.js +2 -0
- package/button.types.js.map +1 -0
- package/demo/{nr-buttons-demo.d.ts → buttons-demo.d.ts} +2 -2
- package/demo/buttons-demo.d.ts.map +1 -0
- package/demo/{nr-buttons-demo.js → buttons-demo.js} +64 -2
- package/demo/buttons-demo.js.map +1 -0
- package/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/mixins/index.d.ts +14 -0
- package/mixins/index.d.ts.map +1 -0
- package/mixins/index.js +10 -0
- package/mixins/index.js.map +1 -0
- package/mixins/keyboard-mixin.d.ts +52 -0
- package/mixins/keyboard-mixin.d.ts.map +1 -0
- package/mixins/keyboard-mixin.js +78 -0
- package/mixins/keyboard-mixin.js.map +1 -0
- package/mixins/link-mixin.d.ts +67 -0
- package/mixins/link-mixin.d.ts.map +1 -0
- package/mixins/link-mixin.js +87 -0
- package/mixins/link-mixin.js.map +1 -0
- package/mixins/ripple-mixin.d.ts +53 -0
- package/mixins/ripple-mixin.d.ts.map +1 -0
- package/mixins/ripple-mixin.js +77 -0
- package/mixins/ripple-mixin.js.map +1 -0
- package/package.json +1 -1
- package/react.d.ts +1 -1
- package/react.d.ts.map +1 -1
- package/react.js +1 -1
- package/react.js.map +1 -1
- package/test/nr-button_test.d.ts +1 -1
- package/test/nr-button_test.d.ts.map +1 -1
- package/test/nr-button_test.js +2 -2
- package/test/nr-button_test.js.map +1 -1
- package/demo/nr-buttons-demo.d.ts.map +0 -1
- package/demo/nr-buttons-demo.js.map +0 -1
- package/nr-button.component.d.ts +0 -36
- package/nr-button.component.d.ts.map +0 -1
- package/nr-button.component.js +0 -99
- package/nr-button.component.js.map +0 -1
- package/nr-button.style.d.ts.map +0 -1
- package/nr-button.style.js.map +0 -1
- package/nr-button.style.variables.d.ts.map +0 -1
- package/nr-button.style.variables.js.map +0 -1
- package/nr-button.types.d.ts.map +0 -1
- package/nr-button.types.js +0 -2
- package/nr-button.types.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.style.variables.js","sourceRoot":"","sources":["../../../src/components/button/button.style.variables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsLjC,CAAC","sourcesContent":["import { css } from 'lit';\n\n/**\n * Button component CSS custom properties (design tokens)\n * \n * This file contains all the CSS custom properties used by the nr-button component,\n * organized by functionality and including both light and dark theme variants.\n * \n * The styling system uses CSS custom properties with fallbacks to allow\n * for both global and local customization of button appearance.\n */\nexport const buttonVariables = css`\n :host {\n /* ----------------------------------------\n * DEFAULT BUTTON STYLES\n * ---------------------------------------- */\n --hybrid-button-local-border-top: 2px solid #d0d0d0;\n --hybrid-button-local-border-bottom: 2px solid #d0d0d0;\n --hybrid-button-local-border-left: 2px solid #d0d0d0;\n --hybrid-button-local-border-right: 2px solid #d0d0d0;\n --hybrid-button-local-border-top-left-radius: 0px;\n --hybrid-button-local-border-top-right-radius: 0px;\n --hybrid-button-local-border-bottom-left-radius: 0px;\n --hybrid-button-local-border-bottom-right-radius: 0px;\n --hybrid-button-local-background-color: #f9f9f9;\n --hybrid-button-local-text-color: #393939;\n --hybrid-button-local-hover-border-color: #1677ff;\n --hybrid-button-local-hover-color: #1677ff;\n --hybrid-button-local-font-size: 0.9rem;\n --hybrid-button-local-font-weight: normal;\n --hybrid-button-local-text-transform: none;\n --hybrid-button-local-active-border-color: #1661b1;\n --hybrid-button-local-active-color: #184d86;\n --hybrid-button-local-disabled-background-color: #c6c6c6;\n --hybrid-button-local-disabled-text-color: #8d8d8d;\n --hybrid-button-local-disabled-border-color: #bbb;\n --hybrid-button-local-height: auto;\n --hybrid-button-local-width: auto;\n --hybrid-button-local-padding-y: 0.5rem;\n --hybrid-button-local-padding-x: 0.6rem;\n --hybrid-button-local-icon-width: 18px;\n --hybrid-button-local-icon-height: 14px;\n\n /* ----------------------------------------\n * PRIMARY BUTTON STYLES\n * ---------------------------------------- */\n --hybrid-button-local-primary-border-color: #0f62fe;\n --hybrid-button-local-primary-background-color: #0f62fe;\n --hybrid-button-local-primary-text-color: #ffffff;\n --hybrid-button-local-primary-outline: 1px solid white;\n --hybrid-button-local-primary-outline-offset: -3px;\n --hybrid-button-local-primary-hover-background-color: #0353e9;\n --hybrid-button-local-primary-hover-border-color: #0353e9;\n --hybrid-button-local-primary-active-background-color: #0f62fe;\n --hybrid-button-local-primary-active-border-color: #0f62fe;\n --hybrid-button-local-primary-disabled-text-color: #8d8d8d;\n --hybrid-button-local-primary-disabled-background-color: #c6c6c6;\n --hybrid-button-local-primary-disabled-border-color: #c6c6c6;\n --hybrid-button-local-primary-dashed-border-color: #ffffff;\n\n /* ----------------------------------------\n * DANGER BUTTON STYLES\n * ---------------------------------------- */\n --hybrid-button-local-danger-background-color: #da1e28;\n --hybrid-button-local-danger-text-color: #ffffff;\n --hybrid-button-local-danger-border-color: #da1e28;\n --hybrid-button-local-danger-outline: 1px solid white;\n --hybrid-button-local-danger-outline-offset: -3px;\n --hybrid-button-local-danger-hover-background-color: #ba1b23;\n --hybrid-button-local-danger-hover-border-color: #ba1b23;\n --hybrid-button-local-danger-active-background-color: #da1e28;\n --hybrid-button-local-danger-active-border-color: #0f62fe;\n --hybrid-button-local-danger-disabled-background-color: #c6c6c6;\n --hybrid-button-local-danger-disabled-text-color: #8d8d8d;\n --hybrid-button-local-danger-disabled-border-color: #c6c6c6;\n --hybrid-button-local-danger-dashed-border-color: #ffffff;\n\n /* ----------------------------------------\n * GHOST BUTTON STYLES\n * ---------------------------------------- */\n --hybrid-button-local-ghost-background-color: #ffffff;\n --hybrid-button-local-ghost-text-color: #0f62fe;\n --hybrid-button-local-ghost-border-color: #ffffff;\n --hybrid-button-local-ghost-active-background-color: #ffffff;\n --hybrid-button-local-ghost-active-text-color: #054ada;\n --hybrid-button-local-ghost-active-border-color: #0f62fe;\n --hybrid-button-local-ghost-hover-background-color: #e5e5e5;\n --hybrid-button-local-ghost-hover-border-color: #e5e5e5;\n --hybrid-button-local-ghost-hover-text-color: #054ada;\n --hybrid-button-local-ghost-disabled-background-color: #ffffff;\n --hybrid-button-local-ghost-disabled-text-color: #c6c6c6;\n --hybrid-button-local-ghost-disabled-border-color: #ffffff;\n --hybrid-button-local-ghost-dashed-border-color: #c6c6c6;\n\n /* ----------------------------------------\n * SECONDARY BUTTON STYLES\n * ---------------------------------------- */\n --hybrid-button-local-secondary-background-color: #393939;\n --hybrid-button-local-secondary-border-color: #393939;\n --hybrid-button-local-secondary-text-color: #ffffff;\n --hybrid-button-local-secondary-outline: 1px solid white;\n --hybrid-button-local-secondary-outline-offset: -3px;\n --hybrid-button-local-secondary-hover-background-color: #4c4c4c;\n --hybrid-button-local-secondary-hover-border-color: #4c4c4c;\n --hybrid-button-local-secondary-active-background-color: #393939;\n --hybrid-button-local-secondary-active-border-color: #0f62fe;\n --hybrid-button-local-secondary-disabled-background-color: #c6c6c6;\n --hybrid-button-local-secondary-disabled-text-color: #8d8d8d;\n --hybrid-button-local-secondary-disabled-border-color: #c6c6c6;\n --hybrid-button-local-secondary-dashed-border-color: #ffffff;\n\n /* ----------------------------------------\n * SIZE VARIANTS\n * ---------------------------------------- */\n /* Large button sizing */\n --hybrid-large-button-local-padding-y: 0.5rem;\n --hybrid-large-button-local-padding-x: 0.9rem;\n --hybrid-large-button-local-font-size: 1rem;\n\n /* Small button sizing */\n --hybrid-small-button-local-padding-y: 0.5rem;\n --hybrid-small-button-local-padding-x: 0.4rem;\n --hybrid-small-button-local-font-size: 0.7rem;\n }\n\n /* ========================================\n * DARK THEME OVERRIDES\n * ======================================== */\n \n /**\n * Dark theme styles using data-theme attribute on button element\n * These override the light theme defaults when data-theme=\"dark\" is applied\n */\n button[data-theme=\"dark\"] {\n /* Default button dark theme overrides */\n --hybrid-button-local-background-color: #000000;\n --hybrid-button-local-text-color: #ffffff;\n --hybrid-button-local-hover-border-color: #6f6f6f;\n --hybrid-button-local-hover-color: #6f6f6f;\n --hybrid-button-local-active-border-color: #c6c6c6;\n --hybrid-button-local-active-color: #c6c6c6;\n --hybrid-button-local-disabled-background-color: #c6c6c6;\n\n /* Primary button dark theme overrides */\n --hybrid-button-local-primary-outline: 1px solid black;\n --hybrid-button-local-primary-outline-offset: -3px;\n --hybrid-button-local-primary-active-border-color: #ffffff;\n --hybrid-button-local-primary-disabled-text-color: #c6c6c6;\n --hybrid-button-local-primary-disabled-background-color: #8d8d8d;\n --hybrid-button-local-primary-disabled-border-color: #8d8d8d;\n\n /* Secondary button dark theme overrides */\n --hybrid-button-local-secondary-background-color: #6f6f6f;\n --hybrid-button-local-secondary-border-color: #6f6f6f;\n --hybrid-button-local-secondary-text-color: #ffffff;\n --hybrid-button-local-secondary-active-border-color: #ffffff;\n --hybrid-button-local-secondary-active-background-color: #6f6f6f;\n --hybrid-button-local-secondary-outline: 1px solid black;\n --hybrid-button-local-secondary-outline-offset: -3px;\n --hybrid-button-local-secondary-hover-background-color: #606060;\n --hybrid-button-local-secondary-hover-border-color: #606060;\n --hybrid-button-local-secondary-disabled-background-color: #6f6f6f;\n --hybrid-button-local-secondary-disabled-text-color: #8d8d8d;\n --hybrid-button-local-secondary-disabled-border-color: #6f6f6f;\n --hybrid-button-local-secondary-dashed-border-color: #ffffff;\n\n /* Ghost button dark theme overrides */\n --hybrid-button-local-ghost-background-color: transparent;\n --hybrid-button-local-ghost-text-color: #78a9ff;\n --hybrid-button-local-ghost-border-color: transparent;\n --hybrid-button-local-ghost-active-background-color: transparent;\n --hybrid-button-local-ghost-active-text-color: #a6c8ff;\n --hybrid-button-local-ghost-active-border-color: #ffffff;\n --hybrid-button-local-ghost-hover-background-color: #4c4c4c;\n --hybrid-button-local-ghost-hover-border-color: #4c4c4c;\n --hybrid-button-local-ghost-hover-text-color: #a6c8ff;\n --hybrid-button-local-ghost-disabled-background-color: transparent;\n --hybrid-button-local-ghost-disabled-text-color: #6f6f6f;\n --hybrid-button-local-ghost-disabled-border-color: transparent;\n --hybrid-button-local-ghost-dashed-border-color: #c6c6c6;\n\n /* Danger button dark theme overrides */\n --hybrid-button-local-danger-outline: 1px solid #000000;\n --hybrid-button-local-danger-outline-offset: -3px;\n --hybrid-button-local-danger-hover-background-color: #ba1b23;\n --hybrid-button-local-danger-hover-border-color: #ba1b23;\n --hybrid-button-local-danger-active-background-color: #da1e28;\n --hybrid-button-local-danger-active-border-color: #ffffff;\n --hybrid-button-local-danger-disabled-background-color: #6f6f6f;\n --hybrid-button-local-danger-disabled-text-color: #8d8d8d;\n --hybrid-button-local-danger-disabled-border-color: #6f6f6f;\n --hybrid-button-local-danger-dashed-border-color: #ffffff;\n }\n`;\n"]}
|
|
@@ -3,16 +3,23 @@ export declare const enum ButtonType {
|
|
|
3
3
|
Secondary = "secondary",
|
|
4
4
|
Danger = "danger",
|
|
5
5
|
Ghost = "ghost",
|
|
6
|
-
Default = "default"
|
|
6
|
+
Default = "default",
|
|
7
|
+
Text = "text",
|
|
8
|
+
Link = "link"
|
|
7
9
|
}
|
|
8
10
|
export declare const enum ButtonSize {
|
|
9
11
|
Small = "small",
|
|
10
12
|
Default = "default",
|
|
11
13
|
Large = "large"
|
|
12
14
|
}
|
|
15
|
+
export declare const enum ButtonShape {
|
|
16
|
+
Default = "default",
|
|
17
|
+
Circle = "circle",
|
|
18
|
+
Round = "round"
|
|
19
|
+
}
|
|
13
20
|
export declare const enum IconPosition {
|
|
14
21
|
Left = "left",
|
|
15
22
|
Right = "right"
|
|
16
23
|
}
|
|
17
24
|
export declare const EMPTY_STRING = "";
|
|
18
|
-
//# sourceMappingURL=
|
|
25
|
+
//# sourceMappingURL=button.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.types.d.ts","sourceRoot":"","sources":["../../../src/components/button/button.types.ts"],"names":[],"mappings":"AAAA,0BAAkB,UAAU;IAC1B,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,MAAM,WAAW;IACjB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,0BAAkB,UAAU;IAC1B,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,0BAAkB,WAAW;IAC3B,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,KAAK,UAAU;CAChB;AAED,0BAAkB,YAAY;IAC5B,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AACD,eAAO,MAAM,YAAY,KAAK,CAAC"}
|
package/button.types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.types.js","sourceRoot":"","sources":["../../../src/components/button/button.types.ts"],"names":[],"mappings":"AA0BA,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC","sourcesContent":["export const enum ButtonType {\n Primary = 'primary',\n Secondary = 'secondary',\n Danger = 'danger',\n Ghost = 'ghost',\n Default = 'default',\n Text = 'text',\n Link = 'link',\n}\n\nexport const enum ButtonSize {\n Small = 'small',\n Default = 'default',\n Large = 'large',\n}\n\nexport const enum ButtonShape {\n Default = 'default',\n Circle = 'circle',\n Round = 'round',\n}\n\nexport const enum IconPosition {\n Left = 'left',\n Right = 'right',\n}\nexport const EMPTY_STRING = '';\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: MIT
|
|
5
5
|
*/
|
|
6
6
|
import { LitElement } from 'lit';
|
|
7
|
-
import '../
|
|
7
|
+
import '../button.component';
|
|
8
8
|
import '../../../helpers/ThemeHandler';
|
|
9
9
|
export declare class ElButtonDemoElement extends LitElement {
|
|
10
10
|
render(): import("lit").TemplateResult<1>;
|
|
@@ -14,4 +14,4 @@ declare global {
|
|
|
14
14
|
'nr-buttons-demo': ElButtonDemoElement;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
//# sourceMappingURL=
|
|
17
|
+
//# sourceMappingURL=buttons-demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buttons-demo.d.ts","sourceRoot":"","sources":["../../../../src/components/button/demo/buttons-demo.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAQ,MAAM,KAAK,CAAC;AAEvC,OAAO,qBAAqB,CAAC;AAC7B,OAAO,+BAA+B,CAAC;AACvC,qBACa,mBAAoB,SAAQ,UAAU;IACxC,MAAM;CA2PhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,mBAAmB,CAAC;KACxC;CACF"}
|
|
@@ -11,7 +11,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
11
11
|
};
|
|
12
12
|
import { LitElement, html } from 'lit';
|
|
13
13
|
import { customElement } from 'lit/decorators.js';
|
|
14
|
-
import '../
|
|
14
|
+
import '../button.component';
|
|
15
15
|
import '../../../helpers/ThemeHandler';
|
|
16
16
|
let ElButtonDemoElement = class ElButtonDemoElement extends LitElement {
|
|
17
17
|
render() {
|
|
@@ -45,6 +45,8 @@ let ElButtonDemoElement = class ElButtonDemoElement extends LitElement {
|
|
|
45
45
|
<td>Ghost</td>
|
|
46
46
|
<td>Danger</td>
|
|
47
47
|
<td>Default</td>
|
|
48
|
+
<td>Text</td>
|
|
49
|
+
<td>Link</td>
|
|
48
50
|
</tr>
|
|
49
51
|
<tr>
|
|
50
52
|
<td>Default</td>
|
|
@@ -63,6 +65,12 @@ let ElButtonDemoElement = class ElButtonDemoElement extends LitElement {
|
|
|
63
65
|
<td>
|
|
64
66
|
<nr-button><span>Default Button</span></nr-button>
|
|
65
67
|
</td>
|
|
68
|
+
<td>
|
|
69
|
+
<nr-button type="text"><span>Text Button</span></nr-button>
|
|
70
|
+
</td>
|
|
71
|
+
<td>
|
|
72
|
+
<nr-button type="link" href="https://example.com"><span>Link Button</span></nr-button>
|
|
73
|
+
</td>
|
|
66
74
|
</tr>
|
|
67
75
|
<tr>
|
|
68
76
|
<td>Dashed</td>
|
|
@@ -81,6 +89,12 @@ let ElButtonDemoElement = class ElButtonDemoElement extends LitElement {
|
|
|
81
89
|
<td>
|
|
82
90
|
<nr-button ?dashed=${true}><span>Default dashed</span></nr-button>
|
|
83
91
|
</td>
|
|
92
|
+
<td>
|
|
93
|
+
<nr-button type="text" ?dashed=${true}><span>Text dashed</span></nr-button>
|
|
94
|
+
</td>
|
|
95
|
+
<td>
|
|
96
|
+
<nr-button type="link" href="https://example.com" ?dashed=${true}><span>Link dashed</span></nr-button>
|
|
97
|
+
</td>
|
|
84
98
|
</tr>
|
|
85
99
|
<tr>
|
|
86
100
|
<td>Loading</td>
|
|
@@ -197,9 +211,57 @@ let ElButtonDemoElement = class ElButtonDemoElement extends LitElement {
|
|
|
197
211
|
<td><nr-button type="ghost" .icon="${['search']}"></nr-button></td>
|
|
198
212
|
<td><nr-button type="danger" .icon="${['search']}"></nr-button></td>
|
|
199
213
|
<td><nr-button .icon="${['search']}"></nr-button></td>
|
|
214
|
+
<td><nr-button type="text" .icon="${['search']}"></nr-button></td>
|
|
215
|
+
<td><nr-button type="link" href="https://example.com" .icon="${['search']}"></nr-button></td>
|
|
200
216
|
</tr>
|
|
201
217
|
</tbody>
|
|
202
218
|
</table>
|
|
219
|
+
|
|
220
|
+
<h1>Button Shapes</h1>
|
|
221
|
+
<br />
|
|
222
|
+
<h3>Default Shape</h3>
|
|
223
|
+
<nr-button type="primary">Default Button</nr-button>
|
|
224
|
+
<nr-button type="primary" .icon="${['search']}">With Icon</nr-button>
|
|
225
|
+
<nr-button type="primary" .icon="${['search']}"></nr-button>
|
|
226
|
+
|
|
227
|
+
<h3>Round Shape</h3>
|
|
228
|
+
<nr-button type="primary" shape="round">Round Button</nr-button>
|
|
229
|
+
<nr-button type="primary" shape="round" .icon="${['search']}">Round With Icon</nr-button>
|
|
230
|
+
<nr-button type="primary" shape="round" .icon="${['search']}"></nr-button>
|
|
231
|
+
|
|
232
|
+
<h3>Circle Shape</h3>
|
|
233
|
+
<nr-button type="primary" shape="circle" .icon="${['search']}"></nr-button>
|
|
234
|
+
<nr-button type="secondary" shape="circle" .icon="${['user']}"></nr-button>
|
|
235
|
+
<nr-button type="danger" shape="circle" .icon="${['trash']}"></nr-button>
|
|
236
|
+
|
|
237
|
+
<h3>Circle Shape - Different Sizes</h3>
|
|
238
|
+
<nr-button type="primary" shape="circle" size="small" .icon="${['search']}"></nr-button>
|
|
239
|
+
<nr-button type="primary" shape="circle" .icon="${['search']}"></nr-button>
|
|
240
|
+
<nr-button type="primary" shape="circle" size="large" .icon="${['search']}"></nr-button>
|
|
241
|
+
|
|
242
|
+
<h1>Block Buttons</h1>
|
|
243
|
+
<br />
|
|
244
|
+
<nr-button type="primary" block>Primary Block Button</nr-button>
|
|
245
|
+
<br />
|
|
246
|
+
<nr-button type="secondary" block>Secondary Block Button</nr-button>
|
|
247
|
+
<br />
|
|
248
|
+
<nr-button type="text" block>Text Block Button</nr-button>
|
|
249
|
+
<br />
|
|
250
|
+
<nr-button type="link" href="https://example.com" block>Link Block Button</nr-button>
|
|
251
|
+
<br />
|
|
252
|
+
|
|
253
|
+
<h1>Link Buttons with Target</h1>
|
|
254
|
+
<br />
|
|
255
|
+
<nr-button type="link" href="https://example.com">Same Tab Link</nr-button>
|
|
256
|
+
<nr-button type="link" href="https://example.com" target="_blank">New Tab Link</nr-button>
|
|
257
|
+
<nr-button type="link" href="https://example.com" target="_blank" .icon="${['external-link']}">External Link</nr-button>
|
|
258
|
+
<br />
|
|
259
|
+
|
|
260
|
+
<h1>Accessibility Examples</h1>
|
|
261
|
+
<br />
|
|
262
|
+
<nr-button type="primary" buttonAriaLabel="Save document">Save</nr-button>
|
|
263
|
+
<nr-button type="danger" buttonAriaLabel="Delete item permanently" .icon="${['trash']}">Delete</nr-button>
|
|
264
|
+
<nr-button type="text" buttonAriaLabel="Close dialog" .icon="${['close']}"></nr-button>
|
|
203
265
|
</theme-handler>
|
|
204
266
|
`;
|
|
205
267
|
}
|
|
@@ -208,4 +270,4 @@ ElButtonDemoElement = __decorate([
|
|
|
208
270
|
customElement('nr-buttons-demo')
|
|
209
271
|
], ElButtonDemoElement);
|
|
210
272
|
export { ElButtonDemoElement };
|
|
211
|
-
//# sourceMappingURL=
|
|
273
|
+
//# sourceMappingURL=buttons-demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buttons-demo.js","sourceRoot":"","sources":["../../../../src/components/button/demo/buttons-demo.ts"],"names":[],"mappings":"AAAA;;;;GAIG;;;;;;;AAEH,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,qBAAqB,CAAC;AAC7B,OAAO,+BAA+B,CAAC;AAEvC,IAAa,mBAAmB,GAAhC,MAAa,mBAAoB,SAAQ,UAAU;IACxC,MAAM;QACb,OAAO,IAAI,CAAA;;;;;;;;4BAQa,CAAC,QAAQ,CAAC;4BACV,CAAC,QAAQ,CAAC;4BACV,CAAC,QAAQ,CAAC;;;4BAGV,CAAC,QAAQ,CAAC;4BACV,CAAC,QAAQ,CAAC;4BACV,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDA6Cc,IAAI;;;sDAGF,IAAI;;;kDAGR,IAAI;;;mDAGH,IAAI;;;qCAGlB,IAAI;;;iDAGQ,IAAI;;;4EAGuB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mDA0C7B,CAAC,QAAQ,CAAC;;;qDAGR,CAAC,QAAQ,CAAC;;;iDAGd,CAAC,QAAQ,CAAC;;;kDAGT,CAAC,QAAQ,CAAC;;;oCAGxB,CAAC,QAAQ,CAAC;;;;;;mDAMK,CAAC,QAAQ,CAAC;;;;;qDAKR,CAAC,QAAQ,CAAC;;;;;iDAKd,CAAC,QAAQ,CAAC;;;;;kDAKT,CAAC,QAAQ,CAAC;;;;;oCAKxB,CAAC,QAAQ,CAAC;;;;;;mDAMK,CAAC,QAAQ,EAAE,MAAM,CAAC;;;;;qDAKhB,CAAC,QAAQ,EAAE,MAAM,CAAC;;;;;iDAKtB,CAAC,QAAQ,EAAE,MAAM,CAAC;;;;;kDAKjB,CAAC,QAAQ,EAAE,MAAM,CAAC;;;;;oCAKhC,CAAC,QAAQ,EAAE,MAAM,CAAC;;;;;;;qDAOD,CAAC,QAAQ,CAAC;uDACR,CAAC,QAAQ,CAAC;mDACd,CAAC,QAAQ,CAAC;oDACT,CAAC,QAAQ,CAAC;sCACxB,CAAC,QAAQ,CAAC;kDACE,CAAC,QAAQ,CAAC;6EACiB,CAAC,QAAQ,CAAC;;;;;;;;;2CAS5C,CAAC,QAAQ,CAAC;2CACV,CAAC,QAAQ,CAAC;;;;yDAII,CAAC,QAAQ,CAAC;yDACV,CAAC,QAAQ,CAAC;;;0DAGT,CAAC,QAAQ,CAAC;4DACR,CAAC,MAAM,CAAC;yDACX,CAAC,OAAO,CAAC;;;uEAGK,CAAC,QAAQ,CAAC;0DACvB,CAAC,QAAQ,CAAC;uEACG,CAAC,QAAQ,CAAC;;;;;;;;;;;;;;;;;mFAiBE,CAAC,eAAe,CAAC;;;;;;oFAMhB,CAAC,OAAO,CAAC;uEACtB,CAAC,OAAO,CAAC;;KAE3E,CAAC;IACJ,CAAC;CACF,CAAA;AA5PY,mBAAmB;IAD/B,aAAa,CAAC,iBAAiB,CAAC;GACpB,mBAAmB,CA4P/B;SA5PY,mBAAmB","sourcesContent":["/**\n * @license\n * Copyright 2023 Google Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\n\nimport { LitElement, html } from 'lit';\nimport { customElement } from 'lit/decorators.js';\nimport '../button.component';\nimport '../../../helpers/ThemeHandler';\n@customElement('nr-buttons-demo')\nexport class ElButtonDemoElement extends LitElement {\n override render() {\n return html`\n <theme-handler>\n <h1>Sizes</h1>\n <br />\n <nr-button> Default Button</nr-button>\n <nr-button size=\"small\">Small Button</nr-button>\n <nr-button size=\"large\">Large Button</nr-button>\n <br /><br />\n <nr-button .icon=\"${['search']}\"> Default Button</nr-button>\n <nr-button .icon=\"${['search']}\" size=\"small\">Small Button</nr-button>\n <nr-button .icon=\"${['search']}\" size=\"large\">Large Button</nr-button>\n\n <br /><br />\n <nr-button .icon=\"${['search']}\"></nr-button>\n <nr-button .icon=\"${['search']}\" size=\"small\"></nr-button>\n <nr-button .icon=\"${['search']}\" size=\"large\"></nr-button>\n <br /><br />\n\n <h1>Types</h1>\n <br /><br />\n\n <table>\n <tbody>\n <tr>\n <td></td>\n <td>Primary</td>\n <td>Secondary</td>\n <td>Ghost</td>\n <td>Danger</td>\n <td>Default</td>\n <td>Text</td>\n <td>Link</td>\n </tr>\n <tr>\n <td>Default</td>\n <td>\n <nr-button type=\"primary\"><span>Primary Button</span></nr-button>\n </td>\n <td>\n <nr-button type=\"secondary\"><span>Secondary Button </span></nr-button>\n </td>\n <td>\n <nr-button type=\"ghost\"> <span>Ghost button</span></nr-button>\n </td>\n <td>\n <nr-button type=\"danger\"><span>Danger Button </span></nr-button>\n </td>\n <td>\n <nr-button><span>Default Button</span></nr-button>\n </td>\n <td>\n <nr-button type=\"text\"><span>Text Button</span></nr-button>\n </td>\n <td>\n <nr-button type=\"link\" href=\"https://example.com\"><span>Link Button</span></nr-button>\n </td>\n </tr>\n <tr>\n <td>Dashed</td>\n <td>\n <nr-button type=\"primary\" ?dashed=${true}><span>Primary Button text only</span></nr-button>\n </td>\n <td>\n <nr-button type=\"secondary\" ?dashed=${true}><span>Secondary dashed</span></nr-button>\n </td>\n <td>\n <nr-button type=\"ghost\" ?dashed=${true}><span>Ghost dashed</span></nr-button>\n </td>\n <td>\n <nr-button type=\"danger\" ?dashed=${true}><span>Danger dashed</span></nr-button>\n </td>\n <td>\n <nr-button ?dashed=${true}><span>Default dashed</span></nr-button>\n </td>\n <td>\n <nr-button type=\"text\" ?dashed=${true}><span>Text dashed</span></nr-button>\n </td>\n <td>\n <nr-button type=\"link\" href=\"https://example.com\" ?dashed=${true}><span>Link dashed</span></nr-button>\n </td>\n </tr>\n <tr>\n <td>Loading</td>\n <td>\n <nr-button type=\"primary\" loading><span>Primary Button loading</span></nr-button>\n </td>\n <td>\n <nr-button type=\"secondary\" loading><span>Secondary button loading </span></nr-button>\n </td>\n <td>\n <nr-button type=\"ghost\" loading><span>Ghost button loading</span></nr-button>\n </td>\n <td>\n <nr-button type=\"danger\" loading><span>Danger button loading</span></nr-button>\n </td>\n <td>\n <nr-button loading><span>Default button loading</span></nr-button>\n </td>\n </tr>\n <tr>\n <td>Disabled</td>\n <td>\n <nr-button type=\"primary\" disabled><span>Primary Button disabled</span></nr-button>\n </td>\n <td>\n <nr-button type=\"secondary\" disabled><span>Secondary Button disabled</span></nr-button>\n </td>\n <td>\n <nr-button type=\"ghost\" disabled> <span>Ghost button disabled</span></nr-button>\n </td>\n <td>\n <nr-button type=\"danger\" disabled><span>Danger Button disabled</span></nr-button>\n </td>\n <td>\n <nr-button disabled><span>Default Button disabled</span></nr-button>\n </td>\n </tr>\n <tr>\n <td>Icon with text default: icon left</td>\n <td>\n <nr-button type=\"primary\" .icon=\"${['search']}\"><span> Primary button icon+text</span></nr-button>\n </td>\n <td>\n <nr-button type=\"secondary\" .icon=\"${['search']}\"><span> Secondary button icon+text</span></nr-button>\n </td>\n <td>\n <nr-button type=\"ghost\" .icon=\"${['search']}\"><span> Ghost button icon+text</span></nr-button>\n </td>\n <td>\n <nr-button type=\"danger\" .icon=\"${['search']}\"><span> Danger button icon+text</span></nr-button>\n </td>\n <td>\n <nr-button .icon=\"${['search']}\"><span> Default button icon+text</span></nr-button>\n </td>\n </tr>\n <tr>\n <td>Icon with text: icon right</td>\n <td>\n <nr-button type=\"primary\" .icon=\"${['search']}\" iconPosition=\"right\"\n ><span> Primary button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button type=\"secondary\" .icon=\"${['search']}\" iconPosition=\"right\"\n ><span> Secondary button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button type=\"ghost\" .icon=\"${['search']}\" iconPosition=\"right\"\n ><span> Ghost button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button type=\"danger\" .icon=\"${['search']}\" iconPosition=\"right\"\n ><span> Danger button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button .icon=\"${['search']}\" iconPosition=\"right\"><span> Default button icon+text</span></nr-button>\n </td>\n </tr>\n <tr>\n <td>Icon with text: icon both side</td>\n <td>\n <nr-button type=\"primary\" .icon=\"${['search', 'bomb']}\" iconPosition=\"right\"\n ><span> Primary button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button type=\"secondary\" .icon=\"${['search', 'bomb']}\" iconPosition=\"right\"\n ><span> Secondary button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button type=\"ghost\" .icon=\"${['search', 'bomb']}\" iconPosition=\"right\"\n ><span> Ghost button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button type=\"danger\" .icon=\"${['search', 'bomb']}\" iconPosition=\"right\"\n ><span> Danger button icon+text</span></nr-button\n >\n </td>\n <td>\n <nr-button .icon=\"${['search', 'bomb']}\" iconPosition=\"right\"\n ><span> Default button icon+text</span></nr-button\n >\n </td>\n </tr>\n <tr>\n <td>Icon only</td>\n <td><nr-button type=\"primary\" .icon=\"${['search']}\"></nr-button></td>\n <td><nr-button type=\"secondary\" .icon=\"${['search']}\"></nr-button></td>\n <td><nr-button type=\"ghost\" .icon=\"${['search']}\"></nr-button></td>\n <td><nr-button type=\"danger\" .icon=\"${['search']}\"></nr-button></td>\n <td><nr-button .icon=\"${['search']}\"></nr-button></td>\n <td><nr-button type=\"text\" .icon=\"${['search']}\"></nr-button></td>\n <td><nr-button type=\"link\" href=\"https://example.com\" .icon=\"${['search']}\"></nr-button></td>\n </tr>\n </tbody>\n </table>\n\n <h1>Button Shapes</h1>\n <br />\n <h3>Default Shape</h3>\n <nr-button type=\"primary\">Default Button</nr-button>\n <nr-button type=\"primary\" .icon=\"${['search']}\">With Icon</nr-button>\n <nr-button type=\"primary\" .icon=\"${['search']}\"></nr-button>\n \n <h3>Round Shape</h3>\n <nr-button type=\"primary\" shape=\"round\">Round Button</nr-button>\n <nr-button type=\"primary\" shape=\"round\" .icon=\"${['search']}\">Round With Icon</nr-button>\n <nr-button type=\"primary\" shape=\"round\" .icon=\"${['search']}\"></nr-button>\n \n <h3>Circle Shape</h3>\n <nr-button type=\"primary\" shape=\"circle\" .icon=\"${['search']}\"></nr-button>\n <nr-button type=\"secondary\" shape=\"circle\" .icon=\"${['user']}\"></nr-button>\n <nr-button type=\"danger\" shape=\"circle\" .icon=\"${['trash']}\"></nr-button>\n\n <h3>Circle Shape - Different Sizes</h3>\n <nr-button type=\"primary\" shape=\"circle\" size=\"small\" .icon=\"${['search']}\"></nr-button>\n <nr-button type=\"primary\" shape=\"circle\" .icon=\"${['search']}\"></nr-button>\n <nr-button type=\"primary\" shape=\"circle\" size=\"large\" .icon=\"${['search']}\"></nr-button>\n\n <h1>Block Buttons</h1>\n <br />\n <nr-button type=\"primary\" block>Primary Block Button</nr-button>\n <br />\n <nr-button type=\"secondary\" block>Secondary Block Button</nr-button>\n <br />\n <nr-button type=\"text\" block>Text Block Button</nr-button>\n <br />\n <nr-button type=\"link\" href=\"https://example.com\" block>Link Block Button</nr-button>\n <br />\n\n <h1>Link Buttons with Target</h1>\n <br />\n <nr-button type=\"link\" href=\"https://example.com\">Same Tab Link</nr-button>\n <nr-button type=\"link\" href=\"https://example.com\" target=\"_blank\">New Tab Link</nr-button>\n <nr-button type=\"link\" href=\"https://example.com\" target=\"_blank\" .icon=\"${['external-link']}\">External Link</nr-button>\n <br />\n\n <h1>Accessibility Examples</h1>\n <br />\n <nr-button type=\"primary\" buttonAriaLabel=\"Save document\">Save</nr-button>\n <nr-button type=\"danger\" buttonAriaLabel=\"Delete item permanently\" .icon=\"${['trash']}\">Delete</nr-button>\n <nr-button type=\"text\" buttonAriaLabel=\"Close dialog\" .icon=\"${['close']}\"></nr-button>\n </theme-handler>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nr-buttons-demo': ElButtonDemoElement;\n }\n}\n"]}
|
package/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './button.component.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
|
package/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './button.component.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/button/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC","sourcesContent":["export * from './button.component.js';\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"}
|
package/mixins/index.js
ADDED
|
@@ -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"]}
|