@duskmoon-dev/el-button 0.2.0 → 0.4.0

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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # @duskmoon-dev/el-button
2
2
 
3
3
  A customizable button component for DuskMoon Elements.
4
+ ok,
4
5
 
5
6
  ## Installation
6
7
 
package/dist/cjs/index.js CHANGED
@@ -36,6 +36,21 @@ module.exports = __toCommonJS(exports_src);
36
36
 
37
37
  // src/el-dm-button.ts
38
38
  var import_el_core = require("@duskmoon-dev/el-core");
39
+ var import_button = require("@duskmoon-dev/core/components/button");
40
+ var VARIANT_CLASSES = {
41
+ primary: "btn-primary",
42
+ secondary: "btn-secondary",
43
+ tertiary: "btn-tertiary",
44
+ ghost: "btn-ghost",
45
+ outline: "btn-outline"
46
+ };
47
+ var SIZE_CLASSES = {
48
+ xs: "btn-xs",
49
+ sm: "btn-sm",
50
+ md: "btn-md",
51
+ lg: "btn-lg"
52
+ };
53
+ var coreStyles = import_button.css.replace(/@layer\s+components\s*\{/, "").replace(/\}\s*$/, "");
39
54
  var styles = import_el_core.css`
40
55
  :host {
41
56
  display: inline-flex;
@@ -46,187 +61,18 @@ var styles = import_el_core.css`
46
61
  display: none !important;
47
62
  }
48
63
 
49
- button {
50
- display: inline-flex;
51
- align-items: center;
52
- justify-content: center;
53
- gap: var(--dm-spacing-sm, 0.5rem);
54
- border: 1px solid transparent;
55
- border-radius: var(--dm-button-border-radius, var(--dm-radius-md, 0.5rem));
56
- font-family: inherit;
57
- font-weight: var(--dm-font-weight-semibold, 600);
58
- cursor: pointer;
59
- transition:
60
- background-color var(--dm-transition-fast, 150ms ease),
61
- border-color var(--dm-transition-fast, 150ms ease),
62
- color var(--dm-transition-fast, 150ms ease),
63
- box-shadow var(--dm-transition-fast, 150ms ease);
64
- -webkit-appearance: none;
65
- appearance: none;
66
- user-select: none;
67
- white-space: nowrap;
68
- }
69
-
70
- button:focus-visible {
71
- outline: none;
72
- box-shadow: var(--dm-focus-ring-offset, 0 0 0 2px white, 0 0 0 4px var(--dm-primary, #3b82f6));
73
- }
74
-
75
- button:disabled {
76
- cursor: not-allowed;
77
- opacity: 0.5;
78
- }
79
-
80
- /* Size variants */
81
- :host([size='xs']) button {
82
- padding: var(--dm-button-padding-y, 0.25rem) var(--dm-button-padding-x, 0.5rem);
83
- font-size: var(--dm-button-font-size, var(--dm-font-size-xs, 0.75rem));
84
- gap: var(--dm-spacing-xs, 0.25rem);
85
- }
86
-
87
- :host([size='sm']) button {
88
- padding: var(--dm-button-padding-y, 0.375rem) var(--dm-button-padding-x, 0.75rem);
89
- font-size: var(--dm-button-font-size, var(--dm-font-size-sm, 0.875rem));
90
- }
91
-
92
- :host(:not([size])) button,
93
- :host([size='md']) button {
94
- padding: var(--dm-button-padding-y, 0.5rem) var(--dm-button-padding-x, 1rem);
95
- font-size: var(--dm-button-font-size, var(--dm-font-size-md, 1rem));
96
- }
97
-
98
- :host([size='lg']) button {
99
- padding: var(--dm-button-padding-y, 0.625rem) var(--dm-button-padding-x, 1.25rem);
100
- font-size: var(--dm-button-font-size, var(--dm-font-size-lg, 1.125rem));
101
- }
102
-
103
- :host([size='xl']) button {
104
- padding: var(--dm-button-padding-y, 0.75rem) var(--dm-button-padding-x, 1.5rem);
105
- font-size: var(--dm-button-font-size, var(--dm-font-size-xl, 1.25rem));
106
- }
107
-
108
- /* Primary variant (default) */
109
- :host(:not([variant])) button,
110
- :host([variant='primary']) button {
111
- background-color: var(--dm-primary, #3b82f6);
112
- color: white;
113
- border-color: var(--dm-primary, #3b82f6);
114
- }
115
-
116
- :host(:not([variant])) button:hover:not(:disabled),
117
- :host([variant='primary']) button:hover:not(:disabled) {
118
- background-color: var(--dm-primary-hover, #2563eb);
119
- border-color: var(--dm-primary-hover, #2563eb);
120
- }
121
-
122
- :host(:not([variant])) button:active:not(:disabled),
123
- :host([variant='primary']) button:active:not(:disabled) {
124
- background-color: var(--dm-primary-active, #1d4ed8);
125
- border-color: var(--dm-primary-active, #1d4ed8);
126
- }
127
-
128
- /* Secondary variant */
129
- :host([variant='secondary']) button {
130
- background-color: var(--dm-secondary, #6b7280);
131
- color: white;
132
- border-color: var(--dm-secondary, #6b7280);
133
- }
134
-
135
- :host([variant='secondary']) button:hover:not(:disabled) {
136
- background-color: var(--dm-secondary-hover, #4b5563);
137
- border-color: var(--dm-secondary-hover, #4b5563);
138
- }
139
-
140
- :host([variant='secondary']) button:active:not(:disabled) {
141
- background-color: var(--dm-secondary-active, #374151);
142
- border-color: var(--dm-secondary-active, #374151);
143
- }
64
+ /* Import core button styles */
65
+ ${coreStyles}
144
66
 
145
- /* Tertiary variant */
146
- :host([variant='tertiary']) button {
147
- background-color: var(--dm-gray-100, #f3f4f6);
148
- color: var(--dm-gray-800, #1f2937);
149
- border-color: var(--dm-gray-100, #f3f4f6);
150
- }
151
-
152
- :host([variant='tertiary']) button:hover:not(:disabled) {
153
- background-color: var(--dm-gray-200, #e5e7eb);
154
- border-color: var(--dm-gray-200, #e5e7eb);
155
- }
156
-
157
- :host([variant='tertiary']) button:active:not(:disabled) {
158
- background-color: var(--dm-gray-300, #d1d5db);
159
- border-color: var(--dm-gray-300, #d1d5db);
160
- }
161
-
162
- /* Ghost variant */
163
- :host([variant='ghost']) button {
164
- background-color: transparent;
165
- color: var(--dm-primary, #3b82f6);
166
- border-color: transparent;
167
- }
168
-
169
- :host([variant='ghost']) button:hover:not(:disabled) {
170
- background-color: var(--dm-gray-100, #f3f4f6);
171
- }
172
-
173
- :host([variant='ghost']) button:active:not(:disabled) {
174
- background-color: var(--dm-gray-200, #e5e7eb);
175
- }
176
-
177
- /* Outline variant */
178
- :host([variant='outline']) button {
179
- background-color: transparent;
180
- color: var(--dm-primary, #3b82f6);
181
- border-color: var(--dm-primary, #3b82f6);
182
- }
183
-
184
- :host([variant='outline']) button:hover:not(:disabled) {
185
- background-color: var(--dm-primary, #3b82f6);
186
- color: white;
187
- }
188
-
189
- :host([variant='outline']) button:active:not(:disabled) {
190
- background-color: var(--dm-primary-hover, #2563eb);
191
- border-color: var(--dm-primary-hover, #2563eb);
192
- color: white;
193
- }
194
-
195
- /* Loading state */
196
- :host([loading]) button {
197
- position: relative;
198
- pointer-events: none;
199
- }
200
-
201
- :host([loading]) .content {
202
- visibility: hidden;
203
- }
204
-
205
- .spinner {
206
- display: none;
207
- position: absolute;
208
- width: 1em;
209
- height: 1em;
210
- border: 2px solid currentColor;
211
- border-top-color: transparent;
212
- border-radius: 50%;
213
- animation: spin 0.6s linear infinite;
214
- }
215
-
216
- :host([loading]) .spinner {
217
- display: block;
218
- }
219
-
220
- @keyframes spin {
221
- to {
222
- transform: rotate(360deg);
223
- }
67
+ /* Web component specific adjustments */
68
+ .btn {
69
+ font-family: inherit;
224
70
  }
225
71
 
226
72
  .content {
227
73
  display: inline-flex;
228
74
  align-items: center;
229
- gap: inherit;
75
+ gap: 0.5rem;
230
76
  }
231
77
 
232
78
  ::slotted(*) {
@@ -269,16 +115,29 @@ class ElDmButton extends import_el_core.BaseElement {
269
115
  super.connectedCallback();
270
116
  this.addEventListener("click", this._handleClick.bind(this));
271
117
  }
118
+ _getButtonClasses() {
119
+ const classes = ["btn"];
120
+ const variantClass = VARIANT_CLASSES[this.variant] || "btn-primary";
121
+ classes.push(variantClass);
122
+ if (this.size && SIZE_CLASSES[this.size]) {
123
+ classes.push(SIZE_CLASSES[this.size]);
124
+ }
125
+ if (this.loading) {
126
+ classes.push("btn-loading");
127
+ }
128
+ return classes.join(" ");
129
+ }
272
130
  render() {
273
131
  const isDisabled = this.disabled || this.loading;
132
+ const buttonClasses = this._getButtonClasses();
274
133
  return `
275
134
  <button
135
+ class="${buttonClasses}"
276
136
  part="button"
277
137
  type="${this.type || "button"}"
278
138
  ${isDisabled ? "disabled" : ""}
279
139
  aria-busy="${this.loading ? "true" : "false"}"
280
140
  >
281
- <span class="spinner" part="spinner"></span>
282
141
  <span class="content" part="content">
283
142
  <slot name="prefix" part="prefix"></slot>
284
143
  <slot></slot>
@@ -296,5 +155,5 @@ function register() {
296
155
  }
297
156
  }
298
157
 
299
- //# debugId=EFE793B77ED6D50064756E2164756E21
158
+ //# debugId=E9AE97A2832CD5A564756E2164756E21
300
159
  //# sourceMappingURL=index.js.map
@@ -2,10 +2,10 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/el-dm-button.ts", "../../src/index.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * DuskMoon Button Element\n *\n * A customizable button component with multiple variants and sizes.\n *\n * @element el-dm-button\n *\n * @attr {string} variant - Button variant: primary, secondary, tertiary, ghost, outline\n * @attr {string} size - Button size: xs, sm, md, lg, xl\n * @attr {boolean} disabled - Whether the button is disabled\n * @attr {string} type - Button type: button, submit, reset\n * @attr {boolean} loading - Whether the button is in loading state\n *\n * @slot - Default slot for button content\n * @slot prefix - Content before the main text\n * @slot suffix - Content after the main text\n *\n * @csspart button - The native button element\n * @csspart content - The content wrapper\n * @csspart prefix - The prefix slot wrapper\n * @csspart suffix - The suffix slot wrapper\n * @csspart spinner - The loading spinner\n *\n * @fires click - Fired when button is clicked (native event)\n *\n * @cssprop --dm-button-padding-x - Horizontal padding\n * @cssprop --dm-button-padding-y - Vertical padding\n * @cssprop --dm-button-font-size - Font size\n * @cssprop --dm-button-border-radius - Border radius\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\nimport type { Size, Variant } from '@duskmoon-dev/el-core';\n\nconst styles = css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--dm-spacing-sm, 0.5rem);\n border: 1px solid transparent;\n border-radius: var(--dm-button-border-radius, var(--dm-radius-md, 0.5rem));\n font-family: inherit;\n font-weight: var(--dm-font-weight-semibold, 600);\n cursor: pointer;\n transition:\n background-color var(--dm-transition-fast, 150ms ease),\n border-color var(--dm-transition-fast, 150ms ease),\n color var(--dm-transition-fast, 150ms ease),\n box-shadow var(--dm-transition-fast, 150ms ease);\n -webkit-appearance: none;\n appearance: none;\n user-select: none;\n white-space: nowrap;\n }\n\n button:focus-visible {\n outline: none;\n box-shadow: var(--dm-focus-ring-offset, 0 0 0 2px white, 0 0 0 4px var(--dm-primary, #3b82f6));\n }\n\n button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n /* Size variants */\n :host([size='xs']) button {\n padding: var(--dm-button-padding-y, 0.25rem) var(--dm-button-padding-x, 0.5rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-xs, 0.75rem));\n gap: var(--dm-spacing-xs, 0.25rem);\n }\n\n :host([size='sm']) button {\n padding: var(--dm-button-padding-y, 0.375rem) var(--dm-button-padding-x, 0.75rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-sm, 0.875rem));\n }\n\n :host(:not([size])) button,\n :host([size='md']) button {\n padding: var(--dm-button-padding-y, 0.5rem) var(--dm-button-padding-x, 1rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-md, 1rem));\n }\n\n :host([size='lg']) button {\n padding: var(--dm-button-padding-y, 0.625rem) var(--dm-button-padding-x, 1.25rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-lg, 1.125rem));\n }\n\n :host([size='xl']) button {\n padding: var(--dm-button-padding-y, 0.75rem) var(--dm-button-padding-x, 1.5rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-xl, 1.25rem));\n }\n\n /* Primary variant (default) */\n :host(:not([variant])) button,\n :host([variant='primary']) button {\n background-color: var(--dm-primary, #3b82f6);\n color: white;\n border-color: var(--dm-primary, #3b82f6);\n }\n\n :host(:not([variant])) button:hover:not(:disabled),\n :host([variant='primary']) button:hover:not(:disabled) {\n background-color: var(--dm-primary-hover, #2563eb);\n border-color: var(--dm-primary-hover, #2563eb);\n }\n\n :host(:not([variant])) button:active:not(:disabled),\n :host([variant='primary']) button:active:not(:disabled) {\n background-color: var(--dm-primary-active, #1d4ed8);\n border-color: var(--dm-primary-active, #1d4ed8);\n }\n\n /* Secondary variant */\n :host([variant='secondary']) button {\n background-color: var(--dm-secondary, #6b7280);\n color: white;\n border-color: var(--dm-secondary, #6b7280);\n }\n\n :host([variant='secondary']) button:hover:not(:disabled) {\n background-color: var(--dm-secondary-hover, #4b5563);\n border-color: var(--dm-secondary-hover, #4b5563);\n }\n\n :host([variant='secondary']) button:active:not(:disabled) {\n background-color: var(--dm-secondary-active, #374151);\n border-color: var(--dm-secondary-active, #374151);\n }\n\n /* Tertiary variant */\n :host([variant='tertiary']) button {\n background-color: var(--dm-gray-100, #f3f4f6);\n color: var(--dm-gray-800, #1f2937);\n border-color: var(--dm-gray-100, #f3f4f6);\n }\n\n :host([variant='tertiary']) button:hover:not(:disabled) {\n background-color: var(--dm-gray-200, #e5e7eb);\n border-color: var(--dm-gray-200, #e5e7eb);\n }\n\n :host([variant='tertiary']) button:active:not(:disabled) {\n background-color: var(--dm-gray-300, #d1d5db);\n border-color: var(--dm-gray-300, #d1d5db);\n }\n\n /* Ghost variant */\n :host([variant='ghost']) button {\n background-color: transparent;\n color: var(--dm-primary, #3b82f6);\n border-color: transparent;\n }\n\n :host([variant='ghost']) button:hover:not(:disabled) {\n background-color: var(--dm-gray-100, #f3f4f6);\n }\n\n :host([variant='ghost']) button:active:not(:disabled) {\n background-color: var(--dm-gray-200, #e5e7eb);\n }\n\n /* Outline variant */\n :host([variant='outline']) button {\n background-color: transparent;\n color: var(--dm-primary, #3b82f6);\n border-color: var(--dm-primary, #3b82f6);\n }\n\n :host([variant='outline']) button:hover:not(:disabled) {\n background-color: var(--dm-primary, #3b82f6);\n color: white;\n }\n\n :host([variant='outline']) button:active:not(:disabled) {\n background-color: var(--dm-primary-hover, #2563eb);\n border-color: var(--dm-primary-hover, #2563eb);\n color: white;\n }\n\n /* Loading state */\n :host([loading]) button {\n position: relative;\n pointer-events: none;\n }\n\n :host([loading]) .content {\n visibility: hidden;\n }\n\n .spinner {\n display: none;\n position: absolute;\n width: 1em;\n height: 1em;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: spin 0.6s linear infinite;\n }\n\n :host([loading]) .spinner {\n display: block;\n }\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .content {\n display: inline-flex;\n align-items: center;\n gap: inherit;\n }\n\n ::slotted(*) {\n display: inline-flex;\n align-items: center;\n }\n`;\n\nexport class ElDmButton extends BaseElement {\n static properties = {\n variant: { type: String, reflect: true },\n size: { type: String, reflect: true },\n disabled: { type: Boolean, reflect: true },\n type: { type: String, reflect: true, default: 'button' },\n loading: { type: Boolean, reflect: true },\n };\n\n /** Button variant */\n declare variant: Variant;\n\n /** Button size */\n declare size: Size;\n\n /** Whether the button is disabled */\n declare disabled: boolean;\n\n /** Button type (button, submit, reset) */\n declare type: 'button' | 'submit' | 'reset';\n\n /** Whether the button is in loading state */\n declare loading: boolean;\n\n constructor() {\n super();\n this.attachStyles(styles);\n }\n\n /**\n * Handle click events\n */\n private _handleClick(event: MouseEvent): void {\n if (this.disabled || this.loading) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Handle form submission\n if (this.type === 'submit') {\n const form = this.closest('form');\n if (form) {\n form.requestSubmit();\n }\n } else if (this.type === 'reset') {\n const form = this.closest('form');\n if (form) {\n form.reset();\n }\n }\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('click', this._handleClick.bind(this));\n }\n\n render(): string {\n const isDisabled = this.disabled || this.loading;\n\n return `\n <button\n part=\"button\"\n type=\"${this.type || 'button'}\"\n ${isDisabled ? 'disabled' : ''}\n aria-busy=\"${this.loading ? 'true' : 'false'}\"\n >\n <span class=\"spinner\" part=\"spinner\"></span>\n <span class=\"content\" part=\"content\">\n <slot name=\"prefix\" part=\"prefix\"></slot>\n <slot></slot>\n <slot name=\"suffix\" part=\"suffix\"></slot>\n </span>\n </button>\n `;\n }\n}\n",
5
+ "/**\n * DuskMoon Button Element\n *\n * A customizable button component with multiple variants and sizes.\n * Uses styles from @duskmoon-dev/core for consistent theming.\n *\n * @element el-dm-button\n *\n * @attr {string} variant - Button variant: primary, secondary, tertiary, ghost, outline\n * @attr {string} size - Button size: xs, sm, md, lg\n * @attr {boolean} disabled - Whether the button is disabled\n * @attr {string} type - Button type: button, submit, reset\n * @attr {boolean} loading - Whether the button is in loading state\n *\n * @slot - Default slot for button content\n * @slot prefix - Content before the main text\n * @slot suffix - Content after the main text\n *\n * @csspart button - The native button element\n * @csspart content - The content wrapper\n * @csspart prefix - The prefix slot wrapper\n * @csspart suffix - The suffix slot wrapper\n *\n * @fires click - Fired when button is clicked (native event)\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\nimport { css as buttonCSS } from '@duskmoon-dev/core/components/button';\n\n// Map of variant attribute values to CSS classes\nconst VARIANT_CLASSES: Record<string, string> = {\n primary: 'btn-primary',\n secondary: 'btn-secondary',\n tertiary: 'btn-tertiary',\n ghost: 'btn-ghost',\n outline: 'btn-outline',\n};\n\n// Map of size attribute values to CSS classes\nconst SIZE_CLASSES: Record<string, string> = {\n xs: 'btn-xs',\n sm: 'btn-sm',\n md: 'btn-md',\n lg: 'btn-lg',\n};\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'outline';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\n\n// Strip @layer wrapper for Shadow DOM compatibility and add host styles\nconst coreStyles = buttonCSS.replace(/@layer\\s+components\\s*\\{/, '').replace(/\\}\\s*$/, '');\n\nconst styles = css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n /* Import core button styles */\n ${coreStyles}\n\n /* Web component specific adjustments */\n .btn {\n font-family: inherit;\n }\n\n .content {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n ::slotted(*) {\n display: inline-flex;\n align-items: center;\n }\n`;\n\nexport class ElDmButton extends BaseElement {\n static properties = {\n variant: { type: String, reflect: true },\n size: { type: String, reflect: true },\n disabled: { type: Boolean, reflect: true },\n type: { type: String, reflect: true, default: 'button' },\n loading: { type: Boolean, reflect: true },\n };\n\n /** Button variant */\n declare variant: ButtonVariant;\n\n /** Button size */\n declare size: ButtonSize;\n\n /** Whether the button is disabled */\n declare disabled: boolean;\n\n /** Button type (button, submit, reset) */\n declare type: 'button' | 'submit' | 'reset';\n\n /** Whether the button is in loading state */\n declare loading: boolean;\n\n constructor() {\n super();\n this.attachStyles(styles);\n }\n\n /**\n * Handle click events\n */\n private _handleClick(event: MouseEvent): void {\n if (this.disabled || this.loading) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Handle form submission\n if (this.type === 'submit') {\n const form = this.closest('form');\n if (form) {\n form.requestSubmit();\n }\n } else if (this.type === 'reset') {\n const form = this.closest('form');\n if (form) {\n form.reset();\n }\n }\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('click', this._handleClick.bind(this));\n }\n\n /**\n * Build CSS class string for the button\n */\n private _getButtonClasses(): string {\n const classes = ['btn'];\n\n // Add variant class (default to primary)\n const variantClass = VARIANT_CLASSES[this.variant] || 'btn-primary';\n classes.push(variantClass);\n\n // Add size class if specified\n if (this.size && SIZE_CLASSES[this.size]) {\n classes.push(SIZE_CLASSES[this.size]);\n }\n\n // Add loading class\n if (this.loading) {\n classes.push('btn-loading');\n }\n\n return classes.join(' ');\n }\n\n render(): string {\n const isDisabled = this.disabled || this.loading;\n const buttonClasses = this._getButtonClasses();\n\n return `\n <button\n class=\"${buttonClasses}\"\n part=\"button\"\n type=\"${this.type || 'button'}\"\n ${isDisabled ? 'disabled' : ''}\n aria-busy=\"${this.loading ? 'true' : 'false'}\"\n >\n <span class=\"content\" part=\"content\">\n <slot name=\"prefix\" part=\"prefix\"></slot>\n <slot></slot>\n <slot name=\"suffix\" part=\"suffix\"></slot>\n </span>\n </button>\n `;\n }\n}\n",
6
6
  "/**\n * @duskmoon-dev/el-button\n *\n * DuskMoon Button custom element\n */\n\nimport { ElDmButton } from './el-dm-button.js';\n\nexport { ElDmButton };\n\n/**\n * Register the el-dm-button custom element\n *\n * @example\n * ```ts\n * import { register } from '@duskmoon-dev/el-button';\n * register();\n * ```\n */\nexport function register(): void {\n if (!customElements.get('el-dm-button')) {\n customElements.define('el-dm-button', ElDmButton);\n }\n}\n"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "EFE793B77ED6D50064756E2164756E21",
8
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BiC,IAAjC;AACiC,IAAjC;AAGA,IAAM,kBAA0C;AAAA,EAC9C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AAAA,EACP,SAAS;AACX;AAGA,IAAM,eAAuC;AAAA,EAC3C,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAMA,IAAM,aAAa,kBAAU,QAAQ,4BAA4B,EAAE,EAAE,QAAQ,UAAU,EAAE;AAEzF,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBG,MAAM,mBAAmB,2BAAY;AAAA,SACnC,aAAa;AAAA,IAClB,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK;AAAA,IACvC,MAAM,EAAE,MAAM,QAAQ,SAAS,KAAK;AAAA,IACpC,UAAU,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IACzC,MAAM,EAAE,MAAM,QAAQ,SAAS,MAAM,SAAS,SAAS;AAAA,IACvD,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,EAC1C;AAAA,EAiBA,WAAW,GAAG;AAAA,IACZ,MAAM;AAAA,IACN,KAAK,aAAa,MAAM;AAAA;AAAA,EAMlB,YAAY,CAAC,OAAyB;AAAA,IAC5C,IAAI,KAAK,YAAY,KAAK,SAAS;AAAA,MACjC,MAAM,eAAe;AAAA,MACrB,MAAM,gBAAgB;AAAA,MACtB;AAAA,IACF;AAAA,IAGA,IAAI,KAAK,SAAS,UAAU;AAAA,MAC1B,MAAM,OAAO,KAAK,QAAQ,MAAM;AAAA,MAChC,IAAI,MAAM;AAAA,QACR,KAAK,cAAc;AAAA,MACrB;AAAA,IACF,EAAO,SAAI,KAAK,SAAS,SAAS;AAAA,MAChC,MAAM,OAAO,KAAK,QAAQ,MAAM;AAAA,MAChC,IAAI,MAAM;AAAA,QACR,KAAK,MAAM;AAAA,MACb;AAAA,IACF;AAAA;AAAA,EAGF,iBAAiB,GAAS;AAAA,IACxB,MAAM,kBAAkB;AAAA,IACxB,KAAK,iBAAiB,SAAS,KAAK,aAAa,KAAK,IAAI,CAAC;AAAA;AAAA,EAMrD,iBAAiB,GAAW;AAAA,IAClC,MAAM,UAAU,CAAC,KAAK;AAAA,IAGtB,MAAM,eAAe,gBAAgB,KAAK,YAAY;AAAA,IACtD,QAAQ,KAAK,YAAY;AAAA,IAGzB,IAAI,KAAK,QAAQ,aAAa,KAAK,OAAO;AAAA,MACxC,QAAQ,KAAK,aAAa,KAAK,KAAK;AAAA,IACtC;AAAA,IAGA,IAAI,KAAK,SAAS;AAAA,MAChB,QAAQ,KAAK,aAAa;AAAA,IAC5B;AAAA,IAEA,OAAO,QAAQ,KAAK,GAAG;AAAA;AAAA,EAGzB,MAAM,GAAW;AAAA,IACf,MAAM,aAAa,KAAK,YAAY,KAAK;AAAA,IACzC,MAAM,gBAAgB,KAAK,kBAAkB;AAAA,IAE7C,OAAO;AAAA;AAAA,iBAEM;AAAA;AAAA,gBAED,KAAK,QAAQ;AAAA,UACnB,aAAa,aAAa;AAAA,qBACf,KAAK,UAAU,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAU7C;;;ACpKO,SAAS,QAAQ,GAAS;AAAA,EAC/B,IAAI,CAAC,eAAe,IAAI,cAAc,GAAG;AAAA,IACvC,eAAe,OAAO,gBAAgB,UAAU;AAAA,EAClD;AAAA;",
9
+ "debugId": "E9AE97A2832CD5A564756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -36,6 +36,21 @@ module.exports = __toCommonJS(exports_src);
36
36
 
37
37
  // src/el-dm-button.ts
38
38
  var import_el_core = require("@duskmoon-dev/el-core");
39
+ var import_button = require("@duskmoon-dev/core/components/button");
40
+ var VARIANT_CLASSES = {
41
+ primary: "btn-primary",
42
+ secondary: "btn-secondary",
43
+ tertiary: "btn-tertiary",
44
+ ghost: "btn-ghost",
45
+ outline: "btn-outline"
46
+ };
47
+ var SIZE_CLASSES = {
48
+ xs: "btn-xs",
49
+ sm: "btn-sm",
50
+ md: "btn-md",
51
+ lg: "btn-lg"
52
+ };
53
+ var coreStyles = import_button.css.replace(/@layer\s+components\s*\{/, "").replace(/\}\s*$/, "");
39
54
  var styles = import_el_core.css`
40
55
  :host {
41
56
  display: inline-flex;
@@ -46,187 +61,18 @@ var styles = import_el_core.css`
46
61
  display: none !important;
47
62
  }
48
63
 
49
- button {
50
- display: inline-flex;
51
- align-items: center;
52
- justify-content: center;
53
- gap: var(--dm-spacing-sm, 0.5rem);
54
- border: 1px solid transparent;
55
- border-radius: var(--dm-button-border-radius, var(--dm-radius-md, 0.5rem));
56
- font-family: inherit;
57
- font-weight: var(--dm-font-weight-semibold, 600);
58
- cursor: pointer;
59
- transition:
60
- background-color var(--dm-transition-fast, 150ms ease),
61
- border-color var(--dm-transition-fast, 150ms ease),
62
- color var(--dm-transition-fast, 150ms ease),
63
- box-shadow var(--dm-transition-fast, 150ms ease);
64
- -webkit-appearance: none;
65
- appearance: none;
66
- user-select: none;
67
- white-space: nowrap;
68
- }
69
-
70
- button:focus-visible {
71
- outline: none;
72
- box-shadow: var(--dm-focus-ring-offset, 0 0 0 2px white, 0 0 0 4px var(--dm-primary, #3b82f6));
73
- }
74
-
75
- button:disabled {
76
- cursor: not-allowed;
77
- opacity: 0.5;
78
- }
79
-
80
- /* Size variants */
81
- :host([size='xs']) button {
82
- padding: var(--dm-button-padding-y, 0.25rem) var(--dm-button-padding-x, 0.5rem);
83
- font-size: var(--dm-button-font-size, var(--dm-font-size-xs, 0.75rem));
84
- gap: var(--dm-spacing-xs, 0.25rem);
85
- }
86
-
87
- :host([size='sm']) button {
88
- padding: var(--dm-button-padding-y, 0.375rem) var(--dm-button-padding-x, 0.75rem);
89
- font-size: var(--dm-button-font-size, var(--dm-font-size-sm, 0.875rem));
90
- }
91
-
92
- :host(:not([size])) button,
93
- :host([size='md']) button {
94
- padding: var(--dm-button-padding-y, 0.5rem) var(--dm-button-padding-x, 1rem);
95
- font-size: var(--dm-button-font-size, var(--dm-font-size-md, 1rem));
96
- }
97
-
98
- :host([size='lg']) button {
99
- padding: var(--dm-button-padding-y, 0.625rem) var(--dm-button-padding-x, 1.25rem);
100
- font-size: var(--dm-button-font-size, var(--dm-font-size-lg, 1.125rem));
101
- }
102
-
103
- :host([size='xl']) button {
104
- padding: var(--dm-button-padding-y, 0.75rem) var(--dm-button-padding-x, 1.5rem);
105
- font-size: var(--dm-button-font-size, var(--dm-font-size-xl, 1.25rem));
106
- }
107
-
108
- /* Primary variant (default) */
109
- :host(:not([variant])) button,
110
- :host([variant='primary']) button {
111
- background-color: var(--dm-primary, #3b82f6);
112
- color: white;
113
- border-color: var(--dm-primary, #3b82f6);
114
- }
115
-
116
- :host(:not([variant])) button:hover:not(:disabled),
117
- :host([variant='primary']) button:hover:not(:disabled) {
118
- background-color: var(--dm-primary-hover, #2563eb);
119
- border-color: var(--dm-primary-hover, #2563eb);
120
- }
121
-
122
- :host(:not([variant])) button:active:not(:disabled),
123
- :host([variant='primary']) button:active:not(:disabled) {
124
- background-color: var(--dm-primary-active, #1d4ed8);
125
- border-color: var(--dm-primary-active, #1d4ed8);
126
- }
127
-
128
- /* Secondary variant */
129
- :host([variant='secondary']) button {
130
- background-color: var(--dm-secondary, #6b7280);
131
- color: white;
132
- border-color: var(--dm-secondary, #6b7280);
133
- }
134
-
135
- :host([variant='secondary']) button:hover:not(:disabled) {
136
- background-color: var(--dm-secondary-hover, #4b5563);
137
- border-color: var(--dm-secondary-hover, #4b5563);
138
- }
139
-
140
- :host([variant='secondary']) button:active:not(:disabled) {
141
- background-color: var(--dm-secondary-active, #374151);
142
- border-color: var(--dm-secondary-active, #374151);
143
- }
64
+ /* Import core button styles */
65
+ ${coreStyles}
144
66
 
145
- /* Tertiary variant */
146
- :host([variant='tertiary']) button {
147
- background-color: var(--dm-gray-100, #f3f4f6);
148
- color: var(--dm-gray-800, #1f2937);
149
- border-color: var(--dm-gray-100, #f3f4f6);
150
- }
151
-
152
- :host([variant='tertiary']) button:hover:not(:disabled) {
153
- background-color: var(--dm-gray-200, #e5e7eb);
154
- border-color: var(--dm-gray-200, #e5e7eb);
155
- }
156
-
157
- :host([variant='tertiary']) button:active:not(:disabled) {
158
- background-color: var(--dm-gray-300, #d1d5db);
159
- border-color: var(--dm-gray-300, #d1d5db);
160
- }
161
-
162
- /* Ghost variant */
163
- :host([variant='ghost']) button {
164
- background-color: transparent;
165
- color: var(--dm-primary, #3b82f6);
166
- border-color: transparent;
167
- }
168
-
169
- :host([variant='ghost']) button:hover:not(:disabled) {
170
- background-color: var(--dm-gray-100, #f3f4f6);
171
- }
172
-
173
- :host([variant='ghost']) button:active:not(:disabled) {
174
- background-color: var(--dm-gray-200, #e5e7eb);
175
- }
176
-
177
- /* Outline variant */
178
- :host([variant='outline']) button {
179
- background-color: transparent;
180
- color: var(--dm-primary, #3b82f6);
181
- border-color: var(--dm-primary, #3b82f6);
182
- }
183
-
184
- :host([variant='outline']) button:hover:not(:disabled) {
185
- background-color: var(--dm-primary, #3b82f6);
186
- color: white;
187
- }
188
-
189
- :host([variant='outline']) button:active:not(:disabled) {
190
- background-color: var(--dm-primary-hover, #2563eb);
191
- border-color: var(--dm-primary-hover, #2563eb);
192
- color: white;
193
- }
194
-
195
- /* Loading state */
196
- :host([loading]) button {
197
- position: relative;
198
- pointer-events: none;
199
- }
200
-
201
- :host([loading]) .content {
202
- visibility: hidden;
203
- }
204
-
205
- .spinner {
206
- display: none;
207
- position: absolute;
208
- width: 1em;
209
- height: 1em;
210
- border: 2px solid currentColor;
211
- border-top-color: transparent;
212
- border-radius: 50%;
213
- animation: spin 0.6s linear infinite;
214
- }
215
-
216
- :host([loading]) .spinner {
217
- display: block;
218
- }
219
-
220
- @keyframes spin {
221
- to {
222
- transform: rotate(360deg);
223
- }
67
+ /* Web component specific adjustments */
68
+ .btn {
69
+ font-family: inherit;
224
70
  }
225
71
 
226
72
  .content {
227
73
  display: inline-flex;
228
74
  align-items: center;
229
- gap: inherit;
75
+ gap: 0.5rem;
230
76
  }
231
77
 
232
78
  ::slotted(*) {
@@ -269,16 +115,29 @@ class ElDmButton extends import_el_core.BaseElement {
269
115
  super.connectedCallback();
270
116
  this.addEventListener("click", this._handleClick.bind(this));
271
117
  }
118
+ _getButtonClasses() {
119
+ const classes = ["btn"];
120
+ const variantClass = VARIANT_CLASSES[this.variant] || "btn-primary";
121
+ classes.push(variantClass);
122
+ if (this.size && SIZE_CLASSES[this.size]) {
123
+ classes.push(SIZE_CLASSES[this.size]);
124
+ }
125
+ if (this.loading) {
126
+ classes.push("btn-loading");
127
+ }
128
+ return classes.join(" ");
129
+ }
272
130
  render() {
273
131
  const isDisabled = this.disabled || this.loading;
132
+ const buttonClasses = this._getButtonClasses();
274
133
  return `
275
134
  <button
135
+ class="${buttonClasses}"
276
136
  part="button"
277
137
  type="${this.type || "button"}"
278
138
  ${isDisabled ? "disabled" : ""}
279
139
  aria-busy="${this.loading ? "true" : "false"}"
280
140
  >
281
- <span class="spinner" part="spinner"></span>
282
141
  <span class="content" part="content">
283
142
  <slot name="prefix" part="prefix"></slot>
284
143
  <slot></slot>
@@ -299,5 +158,5 @@ function register() {
299
158
  // src/register.ts
300
159
  register();
301
160
 
302
- //# debugId=941A37B216B9B18364756E2164756E21
161
+ //# debugId=D5BEEA431377C45A64756E2164756E21
303
162
  //# sourceMappingURL=register.js.map
@@ -2,11 +2,11 @@
2
2
  "version": 3,
3
3
  "sources": ["../../src/el-dm-button.ts", "../../src/index.ts", "../../src/register.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * DuskMoon Button Element\n *\n * A customizable button component with multiple variants and sizes.\n *\n * @element el-dm-button\n *\n * @attr {string} variant - Button variant: primary, secondary, tertiary, ghost, outline\n * @attr {string} size - Button size: xs, sm, md, lg, xl\n * @attr {boolean} disabled - Whether the button is disabled\n * @attr {string} type - Button type: button, submit, reset\n * @attr {boolean} loading - Whether the button is in loading state\n *\n * @slot - Default slot for button content\n * @slot prefix - Content before the main text\n * @slot suffix - Content after the main text\n *\n * @csspart button - The native button element\n * @csspart content - The content wrapper\n * @csspart prefix - The prefix slot wrapper\n * @csspart suffix - The suffix slot wrapper\n * @csspart spinner - The loading spinner\n *\n * @fires click - Fired when button is clicked (native event)\n *\n * @cssprop --dm-button-padding-x - Horizontal padding\n * @cssprop --dm-button-padding-y - Vertical padding\n * @cssprop --dm-button-font-size - Font size\n * @cssprop --dm-button-border-radius - Border radius\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\nimport type { Size, Variant } from '@duskmoon-dev/el-core';\n\nconst styles = css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--dm-spacing-sm, 0.5rem);\n border: 1px solid transparent;\n border-radius: var(--dm-button-border-radius, var(--dm-radius-md, 0.5rem));\n font-family: inherit;\n font-weight: var(--dm-font-weight-semibold, 600);\n cursor: pointer;\n transition:\n background-color var(--dm-transition-fast, 150ms ease),\n border-color var(--dm-transition-fast, 150ms ease),\n color var(--dm-transition-fast, 150ms ease),\n box-shadow var(--dm-transition-fast, 150ms ease);\n -webkit-appearance: none;\n appearance: none;\n user-select: none;\n white-space: nowrap;\n }\n\n button:focus-visible {\n outline: none;\n box-shadow: var(--dm-focus-ring-offset, 0 0 0 2px white, 0 0 0 4px var(--dm-primary, #3b82f6));\n }\n\n button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n /* Size variants */\n :host([size='xs']) button {\n padding: var(--dm-button-padding-y, 0.25rem) var(--dm-button-padding-x, 0.5rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-xs, 0.75rem));\n gap: var(--dm-spacing-xs, 0.25rem);\n }\n\n :host([size='sm']) button {\n padding: var(--dm-button-padding-y, 0.375rem) var(--dm-button-padding-x, 0.75rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-sm, 0.875rem));\n }\n\n :host(:not([size])) button,\n :host([size='md']) button {\n padding: var(--dm-button-padding-y, 0.5rem) var(--dm-button-padding-x, 1rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-md, 1rem));\n }\n\n :host([size='lg']) button {\n padding: var(--dm-button-padding-y, 0.625rem) var(--dm-button-padding-x, 1.25rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-lg, 1.125rem));\n }\n\n :host([size='xl']) button {\n padding: var(--dm-button-padding-y, 0.75rem) var(--dm-button-padding-x, 1.5rem);\n font-size: var(--dm-button-font-size, var(--dm-font-size-xl, 1.25rem));\n }\n\n /* Primary variant (default) */\n :host(:not([variant])) button,\n :host([variant='primary']) button {\n background-color: var(--dm-primary, #3b82f6);\n color: white;\n border-color: var(--dm-primary, #3b82f6);\n }\n\n :host(:not([variant])) button:hover:not(:disabled),\n :host([variant='primary']) button:hover:not(:disabled) {\n background-color: var(--dm-primary-hover, #2563eb);\n border-color: var(--dm-primary-hover, #2563eb);\n }\n\n :host(:not([variant])) button:active:not(:disabled),\n :host([variant='primary']) button:active:not(:disabled) {\n background-color: var(--dm-primary-active, #1d4ed8);\n border-color: var(--dm-primary-active, #1d4ed8);\n }\n\n /* Secondary variant */\n :host([variant='secondary']) button {\n background-color: var(--dm-secondary, #6b7280);\n color: white;\n border-color: var(--dm-secondary, #6b7280);\n }\n\n :host([variant='secondary']) button:hover:not(:disabled) {\n background-color: var(--dm-secondary-hover, #4b5563);\n border-color: var(--dm-secondary-hover, #4b5563);\n }\n\n :host([variant='secondary']) button:active:not(:disabled) {\n background-color: var(--dm-secondary-active, #374151);\n border-color: var(--dm-secondary-active, #374151);\n }\n\n /* Tertiary variant */\n :host([variant='tertiary']) button {\n background-color: var(--dm-gray-100, #f3f4f6);\n color: var(--dm-gray-800, #1f2937);\n border-color: var(--dm-gray-100, #f3f4f6);\n }\n\n :host([variant='tertiary']) button:hover:not(:disabled) {\n background-color: var(--dm-gray-200, #e5e7eb);\n border-color: var(--dm-gray-200, #e5e7eb);\n }\n\n :host([variant='tertiary']) button:active:not(:disabled) {\n background-color: var(--dm-gray-300, #d1d5db);\n border-color: var(--dm-gray-300, #d1d5db);\n }\n\n /* Ghost variant */\n :host([variant='ghost']) button {\n background-color: transparent;\n color: var(--dm-primary, #3b82f6);\n border-color: transparent;\n }\n\n :host([variant='ghost']) button:hover:not(:disabled) {\n background-color: var(--dm-gray-100, #f3f4f6);\n }\n\n :host([variant='ghost']) button:active:not(:disabled) {\n background-color: var(--dm-gray-200, #e5e7eb);\n }\n\n /* Outline variant */\n :host([variant='outline']) button {\n background-color: transparent;\n color: var(--dm-primary, #3b82f6);\n border-color: var(--dm-primary, #3b82f6);\n }\n\n :host([variant='outline']) button:hover:not(:disabled) {\n background-color: var(--dm-primary, #3b82f6);\n color: white;\n }\n\n :host([variant='outline']) button:active:not(:disabled) {\n background-color: var(--dm-primary-hover, #2563eb);\n border-color: var(--dm-primary-hover, #2563eb);\n color: white;\n }\n\n /* Loading state */\n :host([loading]) button {\n position: relative;\n pointer-events: none;\n }\n\n :host([loading]) .content {\n visibility: hidden;\n }\n\n .spinner {\n display: none;\n position: absolute;\n width: 1em;\n height: 1em;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: spin 0.6s linear infinite;\n }\n\n :host([loading]) .spinner {\n display: block;\n }\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .content {\n display: inline-flex;\n align-items: center;\n gap: inherit;\n }\n\n ::slotted(*) {\n display: inline-flex;\n align-items: center;\n }\n`;\n\nexport class ElDmButton extends BaseElement {\n static properties = {\n variant: { type: String, reflect: true },\n size: { type: String, reflect: true },\n disabled: { type: Boolean, reflect: true },\n type: { type: String, reflect: true, default: 'button' },\n loading: { type: Boolean, reflect: true },\n };\n\n /** Button variant */\n declare variant: Variant;\n\n /** Button size */\n declare size: Size;\n\n /** Whether the button is disabled */\n declare disabled: boolean;\n\n /** Button type (button, submit, reset) */\n declare type: 'button' | 'submit' | 'reset';\n\n /** Whether the button is in loading state */\n declare loading: boolean;\n\n constructor() {\n super();\n this.attachStyles(styles);\n }\n\n /**\n * Handle click events\n */\n private _handleClick(event: MouseEvent): void {\n if (this.disabled || this.loading) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Handle form submission\n if (this.type === 'submit') {\n const form = this.closest('form');\n if (form) {\n form.requestSubmit();\n }\n } else if (this.type === 'reset') {\n const form = this.closest('form');\n if (form) {\n form.reset();\n }\n }\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('click', this._handleClick.bind(this));\n }\n\n render(): string {\n const isDisabled = this.disabled || this.loading;\n\n return `\n <button\n part=\"button\"\n type=\"${this.type || 'button'}\"\n ${isDisabled ? 'disabled' : ''}\n aria-busy=\"${this.loading ? 'true' : 'false'}\"\n >\n <span class=\"spinner\" part=\"spinner\"></span>\n <span class=\"content\" part=\"content\">\n <slot name=\"prefix\" part=\"prefix\"></slot>\n <slot></slot>\n <slot name=\"suffix\" part=\"suffix\"></slot>\n </span>\n </button>\n `;\n }\n}\n",
5
+ "/**\n * DuskMoon Button Element\n *\n * A customizable button component with multiple variants and sizes.\n * Uses styles from @duskmoon-dev/core for consistent theming.\n *\n * @element el-dm-button\n *\n * @attr {string} variant - Button variant: primary, secondary, tertiary, ghost, outline\n * @attr {string} size - Button size: xs, sm, md, lg\n * @attr {boolean} disabled - Whether the button is disabled\n * @attr {string} type - Button type: button, submit, reset\n * @attr {boolean} loading - Whether the button is in loading state\n *\n * @slot - Default slot for button content\n * @slot prefix - Content before the main text\n * @slot suffix - Content after the main text\n *\n * @csspart button - The native button element\n * @csspart content - The content wrapper\n * @csspart prefix - The prefix slot wrapper\n * @csspart suffix - The suffix slot wrapper\n *\n * @fires click - Fired when button is clicked (native event)\n */\n\nimport { BaseElement, css } from '@duskmoon-dev/el-core';\nimport { css as buttonCSS } from '@duskmoon-dev/core/components/button';\n\n// Map of variant attribute values to CSS classes\nconst VARIANT_CLASSES: Record<string, string> = {\n primary: 'btn-primary',\n secondary: 'btn-secondary',\n tertiary: 'btn-tertiary',\n ghost: 'btn-ghost',\n outline: 'btn-outline',\n};\n\n// Map of size attribute values to CSS classes\nconst SIZE_CLASSES: Record<string, string> = {\n xs: 'btn-xs',\n sm: 'btn-sm',\n md: 'btn-md',\n lg: 'btn-lg',\n};\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'outline';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\n\n// Strip @layer wrapper for Shadow DOM compatibility and add host styles\nconst coreStyles = buttonCSS.replace(/@layer\\s+components\\s*\\{/, '').replace(/\\}\\s*$/, '');\n\nconst styles = css`\n :host {\n display: inline-flex;\n vertical-align: middle;\n }\n\n :host([hidden]) {\n display: none !important;\n }\n\n /* Import core button styles */\n ${coreStyles}\n\n /* Web component specific adjustments */\n .btn {\n font-family: inherit;\n }\n\n .content {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n ::slotted(*) {\n display: inline-flex;\n align-items: center;\n }\n`;\n\nexport class ElDmButton extends BaseElement {\n static properties = {\n variant: { type: String, reflect: true },\n size: { type: String, reflect: true },\n disabled: { type: Boolean, reflect: true },\n type: { type: String, reflect: true, default: 'button' },\n loading: { type: Boolean, reflect: true },\n };\n\n /** Button variant */\n declare variant: ButtonVariant;\n\n /** Button size */\n declare size: ButtonSize;\n\n /** Whether the button is disabled */\n declare disabled: boolean;\n\n /** Button type (button, submit, reset) */\n declare type: 'button' | 'submit' | 'reset';\n\n /** Whether the button is in loading state */\n declare loading: boolean;\n\n constructor() {\n super();\n this.attachStyles(styles);\n }\n\n /**\n * Handle click events\n */\n private _handleClick(event: MouseEvent): void {\n if (this.disabled || this.loading) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // Handle form submission\n if (this.type === 'submit') {\n const form = this.closest('form');\n if (form) {\n form.requestSubmit();\n }\n } else if (this.type === 'reset') {\n const form = this.closest('form');\n if (form) {\n form.reset();\n }\n }\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('click', this._handleClick.bind(this));\n }\n\n /**\n * Build CSS class string for the button\n */\n private _getButtonClasses(): string {\n const classes = ['btn'];\n\n // Add variant class (default to primary)\n const variantClass = VARIANT_CLASSES[this.variant] || 'btn-primary';\n classes.push(variantClass);\n\n // Add size class if specified\n if (this.size && SIZE_CLASSES[this.size]) {\n classes.push(SIZE_CLASSES[this.size]);\n }\n\n // Add loading class\n if (this.loading) {\n classes.push('btn-loading');\n }\n\n return classes.join(' ');\n }\n\n render(): string {\n const isDisabled = this.disabled || this.loading;\n const buttonClasses = this._getButtonClasses();\n\n return `\n <button\n class=\"${buttonClasses}\"\n part=\"button\"\n type=\"${this.type || 'button'}\"\n ${isDisabled ? 'disabled' : ''}\n aria-busy=\"${this.loading ? 'true' : 'false'}\"\n >\n <span class=\"content\" part=\"content\">\n <slot name=\"prefix\" part=\"prefix\"></slot>\n <slot></slot>\n <slot name=\"suffix\" part=\"suffix\"></slot>\n </span>\n </button>\n `;\n }\n}\n",
6
6
  "/**\n * @duskmoon-dev/el-button\n *\n * DuskMoon Button custom element\n */\n\nimport { ElDmButton } from './el-dm-button.js';\n\nexport { ElDmButton };\n\n/**\n * Register the el-dm-button custom element\n *\n * @example\n * ```ts\n * import { register } from '@duskmoon-dev/el-button';\n * register();\n * ```\n */\nexport function register(): void {\n if (!customElements.get('el-dm-button')) {\n customElements.define('el-dm-button', ElDmButton);\n }\n}\n",
7
7
  "/**\n * Auto-register el-dm-button custom element\n *\n * @example\n * ```ts\n * import '@duskmoon-dev/el-button/register';\n *\n * // Now you can use <el-dm-button> in HTML\n * ```\n */\nimport { register } from './index.js';\n\nregister();\n"
8
8
  ],
9
- "mappings": "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",
10
- "debugId": "941A37B216B9B18364756E2164756E21",
9
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BiC,IAAjC;AACiC,IAAjC;AAGA,IAAM,kBAA0C;AAAA,EAC9C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AAAA,EACP,SAAS;AACX;AAGA,IAAM,eAAuC;AAAA,EAC3C,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAMA,IAAM,aAAa,kBAAU,QAAQ,4BAA4B,EAAE,EAAE,QAAQ,UAAU,EAAE;AAEzF,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBG,MAAM,mBAAmB,2BAAY;AAAA,SACnC,aAAa;AAAA,IAClB,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK;AAAA,IACvC,MAAM,EAAE,MAAM,QAAQ,SAAS,KAAK;AAAA,IACpC,UAAU,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,IACzC,MAAM,EAAE,MAAM,QAAQ,SAAS,MAAM,SAAS,SAAS;AAAA,IACvD,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK;AAAA,EAC1C;AAAA,EAiBA,WAAW,GAAG;AAAA,IACZ,MAAM;AAAA,IACN,KAAK,aAAa,MAAM;AAAA;AAAA,EAMlB,YAAY,CAAC,OAAyB;AAAA,IAC5C,IAAI,KAAK,YAAY,KAAK,SAAS;AAAA,MACjC,MAAM,eAAe;AAAA,MACrB,MAAM,gBAAgB;AAAA,MACtB;AAAA,IACF;AAAA,IAGA,IAAI,KAAK,SAAS,UAAU;AAAA,MAC1B,MAAM,OAAO,KAAK,QAAQ,MAAM;AAAA,MAChC,IAAI,MAAM;AAAA,QACR,KAAK,cAAc;AAAA,MACrB;AAAA,IACF,EAAO,SAAI,KAAK,SAAS,SAAS;AAAA,MAChC,MAAM,OAAO,KAAK,QAAQ,MAAM;AAAA,MAChC,IAAI,MAAM;AAAA,QACR,KAAK,MAAM;AAAA,MACb;AAAA,IACF;AAAA;AAAA,EAGF,iBAAiB,GAAS;AAAA,IACxB,MAAM,kBAAkB;AAAA,IACxB,KAAK,iBAAiB,SAAS,KAAK,aAAa,KAAK,IAAI,CAAC;AAAA;AAAA,EAMrD,iBAAiB,GAAW;AAAA,IAClC,MAAM,UAAU,CAAC,KAAK;AAAA,IAGtB,MAAM,eAAe,gBAAgB,KAAK,YAAY;AAAA,IACtD,QAAQ,KAAK,YAAY;AAAA,IAGzB,IAAI,KAAK,QAAQ,aAAa,KAAK,OAAO;AAAA,MACxC,QAAQ,KAAK,aAAa,KAAK,KAAK;AAAA,IACtC;AAAA,IAGA,IAAI,KAAK,SAAS;AAAA,MAChB,QAAQ,KAAK,aAAa;AAAA,IAC5B;AAAA,IAEA,OAAO,QAAQ,KAAK,GAAG;AAAA;AAAA,EAGzB,MAAM,GAAW;AAAA,IACf,MAAM,aAAa,KAAK,YAAY,KAAK;AAAA,IACzC,MAAM,gBAAgB,KAAK,kBAAkB;AAAA,IAE7C,OAAO;AAAA;AAAA,iBAEM;AAAA;AAAA,gBAED,KAAK,QAAQ;AAAA,UACnB,aAAa,aAAa;AAAA,qBACf,KAAK,UAAU,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAU7C;;;ACpKO,SAAS,QAAQ,GAAS;AAAA,EAC/B,IAAI,CAAC,eAAe,IAAI,cAAc,GAAG;AAAA,IACvC,eAAe,OAAO,gBAAgB,UAAU;AAAA,EAClD;AAAA;;;ACVF,SAAS;",
10
+ "debugId": "D5BEEA431377C45A64756E2164756E21",
11
11
  "names": []
12
12
  }