mn-angular-lib 1.0.99 → 1.0.100

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.
@@ -253,6 +253,11 @@ const mnButtonVariants = tv({
253
253
  disabled: {
254
254
  true: 'opacity-50 pointer-events-none',
255
255
  },
256
+ // Busy state: dim and block interaction like `disabled`, and hint the wait cursor.
257
+ // The spinner itself is rendered in the template (see mn-button.html).
258
+ loading: {
259
+ true: 'opacity-50 pointer-events-none cursor-wait',
260
+ },
256
261
  wrap: {
257
262
  true: 'whitespace-normal',
258
263
  false: 'whitespace-nowrap',
@@ -333,6 +338,7 @@ const mnButtonVariants = tv({
333
338
  color: 'primary',
334
339
  borderRadius: 'lg',
335
340
  disabled: false,
341
+ loading: false,
336
342
  wrap: false,
337
343
  hover: true,
338
344
  },
@@ -340,6 +346,7 @@ const mnButtonVariants = tv({
340
346
 
341
347
  class MnButton {
342
348
  data = {};
349
+ // A loading button is treated as non-interactive: it blocks clicks and is unfocusable,
343
350
  // Bind the computed classes to the host element
344
351
  get hostClasses() {
345
352
  return mnButtonVariants({
@@ -348,33 +355,45 @@ class MnButton {
348
355
  color: this.data.color,
349
356
  borderRadius: this.data.borderRadius,
350
357
  disabled: this.data.disabled,
358
+ loading: this.data.loading,
351
359
  wrap: this.data.wrap,
352
360
  hover: this.data.hover,
353
361
  });
354
362
  }
363
+ // Signals assistive tech that the control is busy while a loading action runs.
364
+ get ariaBusy() {
365
+ return this.data.loading ? 'true' : null;
366
+ }
355
367
  // For accessibility (works for both <button> and <a>)
356
368
  get ariaDisabled() {
357
369
  return this.data.disabled ? 'true' : null;
358
370
  }
359
371
  // Only meaningful for <button>. For <a> it does nothing semantically.
360
372
  get disabledAttr() {
361
- return this.data.disabled ? '' : null;
373
+ return this.isBlocked ? '' : null;
362
374
  }
363
- // Make disabled anchors unfocusable + prevent activation
375
+ // Make disabled/loading anchors unfocusable + prevent activation
364
376
  get tabIndex() {
365
- return this.data.disabled ? '-1' : null;
377
+ return this.isBlocked ? '-1' : null;
378
+ }
379
+ // so an in-flight action cannot be triggered a second time.
380
+ get isBlocked() {
381
+ return !!(this.data.disabled || this.data.loading);
366
382
  }
367
383
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
368
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: MnButton, isStandalone: true, selector: "button[mnButton], a[mnButton]", inputs: { data: "data" }, host: { properties: { "class": "this.hostClasses", "attr.aria-disabled": "this.ariaDisabled", "attr.disabled": "this.disabledAttr", "attr.tabindex": "this.tabIndex" } }, ngImport: i0, template: "<ng-content></ng-content>\n" });
384
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnButton, isStandalone: true, selector: "button[mnButton], a[mnButton]", inputs: { data: "data" }, host: { properties: { "class": "this.hostClasses", "attr.aria-busy": "this.ariaBusy", "attr.aria-disabled": "this.ariaDisabled", "attr.disabled": "this.disabledAttr", "attr.tabindex": "this.tabIndex" } }, ngImport: i0, template: "@if (data.loading) {\n <span\n aria-hidden=\"true\"\n class=\"inline-block h-4 w-4 shrink-0 mr-2 animate-spin rounded-full border-2 border-current border-r-transparent\"\n ></span>\n}\n<ng-content></ng-content>\n" });
369
385
  }
370
386
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnButton, decorators: [{
371
387
  type: Component,
372
- args: [{ selector: 'button[mnButton], a[mnButton]', standalone: true, template: "<ng-content></ng-content>\n" }]
388
+ args: [{ selector: 'button[mnButton], a[mnButton]', standalone: true, template: "@if (data.loading) {\n <span\n aria-hidden=\"true\"\n class=\"inline-block h-4 w-4 shrink-0 mr-2 animate-spin rounded-full border-2 border-current border-r-transparent\"\n ></span>\n}\n<ng-content></ng-content>\n" }]
373
389
  }], propDecorators: { data: [{
374
390
  type: Input
375
391
  }], hostClasses: [{
376
392
  type: HostBinding,
377
393
  args: ['class']
394
+ }], ariaBusy: [{
395
+ type: HostBinding,
396
+ args: ['attr.aria-busy']
378
397
  }], ariaDisabled: [{
379
398
  type: HostBinding,
380
399
  args: ['attr.aria-disabled']