@cdevhub/ngx-tw 0.5.0 → 0.6.1
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 +78 -15
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +11 -2
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-item.mjs +28 -4
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
- package/fesm2022/{cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs → cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs} +3 -3
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +23 -7
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
- package/fesm2022/{cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs → cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs} +107 -19
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +21 -13
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
- package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
- package/index.json +1 -1
- package/package.json +63 -2
- package/theme/_base.css +13 -0
- package/theme/_dark.css +111 -36
- package/theme/_high-contrast-dark.css +367 -0
- package/theme/_high-contrast.css +13 -2
- package/theme/_light.css +332 -0
- package/theme/_semantic.css +60 -26
- package/theme/_typography.css +17 -0
- package/theme/index.css +86 -7
- package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
- package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
- package/types/cdevhub-ngx-tw-button.d.ts +1 -0
- package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
- package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
- package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
- package/types/cdevhub-ngx-tw-card.d.ts +11 -3
- package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
- package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
- package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
- package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
- package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
- package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
- package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
- package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
- package/types/cdevhub-ngx-tw-core.d.ts +152 -21
- package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
- package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
- package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
- package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
- package/types/cdevhub-ngx-tw-dialog.d.ts +12 -3
- package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
- package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
- package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
- package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
- package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
- package/types/cdevhub-ngx-tw-input.d.ts +5 -8
- package/types/cdevhub-ngx-tw-item.d.ts +2 -0
- package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
- package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
- package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
- package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
- package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
- package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
- package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
- package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
- package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
- package/types/cdevhub-ngx-tw-select.d.ts +104 -33
- package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
- package/types/cdevhub-ngx-tw-sheet.d.ts +19 -3
- package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
- package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
- package/types/cdevhub-ngx-tw-split.d.ts +32 -2
- package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
- package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
- package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
- package/types/cdevhub-ngx-tw-table.d.ts +53 -10
- package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
- package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
- package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
- package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
- package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
- package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
- package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
- package/types/cdevhub-ngx-tw-toast.d.ts +20 -6
- package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
- package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
- package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
- package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs.map +0 -1
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map +0 -1
|
@@ -2,6 +2,10 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { input, computed, ChangeDetectionStrategy, Component, inject, Directive } from '@angular/core';
|
|
3
3
|
import { tv } from 'tailwind-variants';
|
|
4
4
|
|
|
5
|
+
/** Maps every legacy spelling onto its canonical replacement. */
|
|
6
|
+
const VARIANT_ALIASES = {
|
|
7
|
+
outlined: 'outline',
|
|
8
|
+
};
|
|
5
9
|
const cardVariants = tv({
|
|
6
10
|
slots: {
|
|
7
11
|
root: 'rounded-lg text-fg overflow-hidden',
|
|
@@ -15,7 +19,7 @@ const cardVariants = tv({
|
|
|
15
19
|
elevated: {
|
|
16
20
|
root: 'bg-surface-raised shadow hover:shadow-md transition-shadow duration-normal motion-reduce:transition-none',
|
|
17
21
|
},
|
|
18
|
-
|
|
22
|
+
outline: {
|
|
19
23
|
root: 'bg-surface border border-border',
|
|
20
24
|
},
|
|
21
25
|
ghost: {
|
|
@@ -41,13 +45,13 @@ const cardVariants = tv({
|
|
|
41
45
|
},
|
|
42
46
|
},
|
|
43
47
|
compoundVariants: [
|
|
44
|
-
{ variant: '
|
|
45
|
-
{ variant: '
|
|
46
|
-
{ variant: '
|
|
47
|
-
{ variant: '
|
|
48
|
-
{ variant: '
|
|
49
|
-
{ variant: '
|
|
50
|
-
{ variant: '
|
|
48
|
+
{ variant: 'outline', color: 'primary', class: { root: 'border-primary-300' } },
|
|
49
|
+
{ variant: 'outline', color: 'secondary', class: { root: 'border-secondary-300' } },
|
|
50
|
+
{ variant: 'outline', color: 'accent', class: { root: 'border-accent-300' } },
|
|
51
|
+
{ variant: 'outline', color: 'info', class: { root: 'border-info-300' } },
|
|
52
|
+
{ variant: 'outline', color: 'success', class: { root: 'border-success-300' } },
|
|
53
|
+
{ variant: 'outline', color: 'warning', class: { root: 'border-warning-300' } },
|
|
54
|
+
{ variant: 'outline', color: 'error', class: { root: 'border-error-300' } },
|
|
51
55
|
],
|
|
52
56
|
defaultVariants: {
|
|
53
57
|
variant: 'elevated',
|
|
@@ -58,17 +62,23 @@ const cardVariants = tv({
|
|
|
58
62
|
twMerge: true,
|
|
59
63
|
});
|
|
60
64
|
class CardComponent {
|
|
61
|
-
/** Controls the visual elevation style. Defaults to `'elevated'`. */
|
|
65
|
+
/** Controls the visual elevation style. Defaults to `'elevated'`. `'outlined'` is a deprecated alias for `'outline'` and renders identically. */
|
|
62
66
|
variant = input('elevated', /* @ts-ignore */
|
|
63
67
|
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
64
|
-
/** Sets the semantic color for bordered regions. Only applies to `
|
|
68
|
+
/** Sets the semantic color for bordered regions. Only applies to `outline` variant borders. Defaults to `'neutral'`. */
|
|
65
69
|
color = input('neutral', /* @ts-ignore */
|
|
66
70
|
...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
67
71
|
/** Controls padding of header, body, and footer sections. Defaults to `'md'`. */
|
|
68
72
|
size = input('md', /* @ts-ignore */
|
|
69
73
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
74
|
+
/** @internal Canonical variant with legacy spellings folded in. */
|
|
75
|
+
resolvedVariant = computed(() => {
|
|
76
|
+
const v = this.variant();
|
|
77
|
+
return VARIANT_ALIASES[v] ?? v;
|
|
78
|
+
}, /* @ts-ignore */
|
|
79
|
+
...(ngDevMode ? [{ debugName: "resolvedVariant" }] : /* istanbul ignore next */ []));
|
|
70
80
|
variantResult = computed(() => cardVariants({
|
|
71
|
-
variant: this.
|
|
81
|
+
variant: this.resolvedVariant(),
|
|
72
82
|
color: this.color(),
|
|
73
83
|
size: this.size(),
|
|
74
84
|
}), /* @ts-ignore */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdevhub-ngx-tw-card.mjs","sources":["../../../projects/ngx-tw/card/card.ts","../../../projects/ngx-tw/card/cdevhub-ngx-tw-card.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n Directive,\n inject,\n input,\n} from '@angular/core';\nimport { tv } from 'tailwind-variants';\nimport type { TwColor, TwSize } from '@cdevhub/ngx-tw/core';\n\n/** Visual style of the card container. */\nexport type CardVariant = 'elevated' | 'outlined' | 'ghost';\n\nconst cardVariants = tv({\n slots: {\n root: 'rounded-lg text-fg overflow-hidden',\n header: 'text-sm font-semibold text-fg border-b border-border',\n body: 'text-sm text-fg',\n footer: 'text-xs text-fg-muted border-t border-border',\n media: 'w-full overflow-hidden',\n },\n variants: {\n variant: {\n elevated: {\n root: 'bg-surface-raised shadow hover:shadow-md transition-shadow duration-normal motion-reduce:transition-none',\n },\n outlined: {\n root: 'bg-surface border border-border',\n },\n ghost: {\n root: 'bg-transparent',\n },\n },\n size: {\n xs: { header: 'p-2', body: 'p-2', footer: 'p-2' },\n sm: { header: 'p-3', body: 'p-3', footer: 'p-3' },\n md: { header: 'p-4', body: 'p-4', footer: 'p-4' },\n lg: { header: 'p-6', body: 'p-6', footer: 'p-6' },\n xl: { header: 'p-8', body: 'p-8', footer: 'p-8' },\n },\n color: {\n primary: {},\n secondary: {},\n accent: {},\n neutral: {},\n info: {},\n success: {},\n warning: {},\n error: {},\n },\n },\n compoundVariants: [\n { variant: 'outlined', color: 'primary', class: { root: 'border-primary-300' } },\n { variant: 'outlined', color: 'secondary', class: { root: 'border-secondary-300' } },\n { variant: 'outlined', color: 'accent', class: { root: 'border-accent-300' } },\n { variant: 'outlined', color: 'info', class: { root: 'border-info-300' } },\n { variant: 'outlined', color: 'success', class: { root: 'border-success-300' } },\n { variant: 'outlined', color: 'warning', class: { root: 'border-warning-300' } },\n { variant: 'outlined', color: 'error', class: { root: 'border-error-300' } },\n ],\n defaultVariants: {\n variant: 'elevated',\n color: 'neutral',\n size: 'md',\n },\n}, {\n twMerge: true,\n});\n\n@Component({\n selector: 'tw-card',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'rootClasses()',\n },\n template: `<ng-content />`,\n})\nexport class CardComponent {\n /** Controls the visual elevation style. Defaults to `'elevated'`. */\n readonly variant = input<CardVariant>('elevated');\n\n /** Sets the semantic color for bordered regions. Only applies to `outlined` variant borders. Defaults to `'neutral'`. */\n readonly color = input<TwColor>('neutral');\n\n /** Controls padding of header, body, and footer sections. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n private readonly variantResult = computed(() =>\n cardVariants({\n variant: this.variant(),\n color: this.color(),\n size: this.size(),\n }),\n );\n\n readonly rootClasses = computed(() => this.variantResult().root());\n readonly headerClasses = computed(() => this.variantResult().header());\n readonly bodyClasses = computed(() => this.variantResult().body());\n readonly footerClasses = computed(() => this.variantResult().footer());\n readonly mediaClasses = computed(() => this.variantResult().media());\n}\n\n@Directive({\n selector: '[twCardHeader]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardHeaderDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.headerClasses;\n}\n\n@Directive({\n selector: '[twCardBody]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardBodyDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.bodyClasses;\n}\n\n@Directive({\n selector: '[twCardFooter]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardFooterDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.footerClasses;\n}\n\n@Directive({\n selector: '[twCardMedia]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardMediaDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.mediaClasses;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cdevhub-ngx-tw-card.mjs","sources":["../../../projects/ngx-tw/card/card.ts","../../../projects/ngx-tw/card/cdevhub-ngx-tw-card.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n Directive,\n inject,\n input,\n} from '@angular/core';\nimport { tv } from 'tailwind-variants';\nimport type { TwColor, TwSize } from '@cdevhub/ngx-tw/core';\n\n/** Visual style of the card container. */\nexport type CardVariant = 'elevated' | 'outline' | 'ghost' | CardVariantLegacy;\n\n/**\n * Legacy `variant` spellings, kept so existing templates keep compiling.\n * @deprecated `'outlined'` is an alias for `'outline'` and renders identically.\n * It will be removed in the next major — prefer `'outline'`.\n */\nexport type CardVariantLegacy = 'outlined';\n\n/** Canonical `variant` spellings — the set `tv()` actually keys on. */\ntype CardVariantCanonical = Exclude<CardVariant, CardVariantLegacy>;\n\n/** Maps every legacy spelling onto its canonical replacement. */\nconst VARIANT_ALIASES: Readonly<Record<CardVariantLegacy, CardVariantCanonical>> = {\n outlined: 'outline',\n};\n\nconst cardVariants = tv({\n slots: {\n root: 'rounded-lg text-fg overflow-hidden',\n header: 'text-sm font-semibold text-fg border-b border-border',\n body: 'text-sm text-fg',\n footer: 'text-xs text-fg-muted border-t border-border',\n media: 'w-full overflow-hidden',\n },\n variants: {\n variant: {\n elevated: {\n root: 'bg-surface-raised shadow hover:shadow-md transition-shadow duration-normal motion-reduce:transition-none',\n },\n outline: {\n root: 'bg-surface border border-border',\n },\n ghost: {\n root: 'bg-transparent',\n },\n },\n size: {\n xs: { header: 'p-2', body: 'p-2', footer: 'p-2' },\n sm: { header: 'p-3', body: 'p-3', footer: 'p-3' },\n md: { header: 'p-4', body: 'p-4', footer: 'p-4' },\n lg: { header: 'p-6', body: 'p-6', footer: 'p-6' },\n xl: { header: 'p-8', body: 'p-8', footer: 'p-8' },\n },\n color: {\n primary: {},\n secondary: {},\n accent: {},\n neutral: {},\n info: {},\n success: {},\n warning: {},\n error: {},\n },\n },\n compoundVariants: [\n { variant: 'outline', color: 'primary', class: { root: 'border-primary-300' } },\n { variant: 'outline', color: 'secondary', class: { root: 'border-secondary-300' } },\n { variant: 'outline', color: 'accent', class: { root: 'border-accent-300' } },\n { variant: 'outline', color: 'info', class: { root: 'border-info-300' } },\n { variant: 'outline', color: 'success', class: { root: 'border-success-300' } },\n { variant: 'outline', color: 'warning', class: { root: 'border-warning-300' } },\n { variant: 'outline', color: 'error', class: { root: 'border-error-300' } },\n ],\n defaultVariants: {\n variant: 'elevated',\n color: 'neutral',\n size: 'md',\n },\n}, {\n twMerge: true,\n});\n\n@Component({\n selector: 'tw-card',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'rootClasses()',\n },\n template: `<ng-content />`,\n})\nexport class CardComponent {\n /** Controls the visual elevation style. Defaults to `'elevated'`. `'outlined'` is a deprecated alias for `'outline'` and renders identically. */\n readonly variant = input<CardVariant>('elevated');\n\n /** Sets the semantic color for bordered regions. Only applies to `outline` variant borders. Defaults to `'neutral'`. */\n readonly color = input<TwColor>('neutral');\n\n /** Controls padding of header, body, and footer sections. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /** @internal Canonical variant with legacy spellings folded in. */\n private readonly resolvedVariant = computed<CardVariantCanonical>(() => {\n const v = this.variant();\n return (VARIANT_ALIASES as Record<string, CardVariantCanonical | undefined>)[v] ?? (v as CardVariantCanonical);\n });\n\n private readonly variantResult = computed(() =>\n cardVariants({\n variant: this.resolvedVariant(),\n color: this.color(),\n size: this.size(),\n }),\n );\n\n readonly rootClasses = computed(() => this.variantResult().root());\n readonly headerClasses = computed(() => this.variantResult().header());\n readonly bodyClasses = computed(() => this.variantResult().body());\n readonly footerClasses = computed(() => this.variantResult().footer());\n readonly mediaClasses = computed(() => this.variantResult().media());\n}\n\n@Directive({\n selector: '[twCardHeader]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardHeaderDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.headerClasses;\n}\n\n@Directive({\n selector: '[twCardBody]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardBodyDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.bodyClasses;\n}\n\n@Directive({\n selector: '[twCardFooter]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardFooterDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.footerClasses;\n}\n\n@Directive({\n selector: '[twCardMedia]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class CardMediaDirective {\n private readonly card = inject(CardComponent);\n readonly classes = this.card.mediaClasses;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -2,14 +2,20 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { input, inject, ElementRef, signal, computed, ChangeDetectionStrategy, Component, model, output, DestroyRef, viewChild, contentChildren, afterNextRender, isDevMode, effect, untracked, Directive } from '@angular/core';
|
|
3
3
|
import { tv } from 'tailwind-variants';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Carousel label resolution — the English defaults and the `{placeholder}`
|
|
7
|
+
* interpolation both `CarouselSlideComponent` (per-slide `aria-label`) and
|
|
8
|
+
* `CarouselIndicatorsComponent` (per-page `aria-label`) read.
|
|
9
|
+
*
|
|
10
|
+
* `formatLabel` is exported so those two files can share one implementation;
|
|
11
|
+
* it is deliberately **not** re-exported from `index.ts` and carries no
|
|
12
|
+
* compatibility promise.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Default English labels used when consumers do not override via the `labels`
|
|
16
|
+
* input. Typed `Required<TwCarouselLabels>` so readers keep a non-optional
|
|
17
|
+
* `string` for every key even though the interface itself is all-optional.
|
|
18
|
+
*/
|
|
13
19
|
const DEFAULT_CAROUSEL_LABELS = {
|
|
14
20
|
previous: 'Previous slide',
|
|
15
21
|
next: 'Next slide',
|
|
@@ -19,12 +25,34 @@ const DEFAULT_CAROUSEL_LABELS = {
|
|
|
19
25
|
slideOfWithLabel: '{index} of {total}: {label}',
|
|
20
26
|
slideOf: '{index} of {total}',
|
|
21
27
|
};
|
|
22
|
-
|
|
23
|
-
/** Replaces `{key}` placeholders in `template` with values from `vars`. Ported from paginator. */
|
|
28
|
+
/** @internal Replaces `{key}` placeholders in `template` with values from `vars`. Ported from paginator. */
|
|
24
29
|
function formatLabel(template, vars) {
|
|
30
|
+
// Defence in depth. `resolvedLabels()` already filters explicitly-undefined
|
|
31
|
+
// consumer keys, so a non-string cannot reach here through the public
|
|
32
|
+
// `labels` input today. The guard exists so a future regression in that
|
|
33
|
+
// merge degrades to a missing label instead of throwing inside a `computed`
|
|
34
|
+
// and taking the render down.
|
|
35
|
+
if (typeof template !== 'string')
|
|
36
|
+
return '';
|
|
25
37
|
return template.replace(/\{(\w+)\}/g, (match, key) => Object.prototype.hasOwnProperty.call(vars, key) ? String(vars[key]) : match);
|
|
26
38
|
}
|
|
27
|
-
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Carousel styling source of truth — the `tv()` slot config plus the pixel
|
|
42
|
+
* mirror of its gap scale.
|
|
43
|
+
*
|
|
44
|
+
* Shared by `carousel.ts` and `carousel-indicators.ts`, which is the only
|
|
45
|
+
* reason it is a separate file; it is **not** exported from `index.ts` and is
|
|
46
|
+
* not consumer API (CLAUDE.md: "Do not export variant configs").
|
|
47
|
+
*
|
|
48
|
+
* `GAP_PX` lives here rather than beside `slideBasis()` because it is the
|
|
49
|
+
* numeric mirror of the `gap-x-*` / `gap-y-*` compound variants below —
|
|
50
|
+
* editing the `md` row from `gap-x-4` to `gap-x-5` without editing `GAP_PX`
|
|
51
|
+
* from 16 to 20 silently miscomputes every slide's `flex-basis`. Co-locating
|
|
52
|
+
* them makes this file the single place a reviewer edits carousel gap
|
|
53
|
+
* geometry.
|
|
54
|
+
*/
|
|
55
|
+
/** @internal Pixel value of the inter-slide gap, used to compute the slide-basis CSS variable. */
|
|
28
56
|
const GAP_PX = {
|
|
29
57
|
xs: 8,
|
|
30
58
|
sm: 12,
|
|
@@ -32,64 +60,6 @@ const GAP_PX = {
|
|
|
32
60
|
lg: 24,
|
|
33
61
|
xl: 32,
|
|
34
62
|
};
|
|
35
|
-
// ── Static color × state class lookups ──
|
|
36
|
-
// Tailwind v4 only resolves statically-written class names. Per the stepper
|
|
37
|
-
// precedent, every color × active/inactive indicator combination is enumerated.
|
|
38
|
-
// Active indicators are also distinguishable by more than color (WCAG 1.4.1):
|
|
39
|
-
// `dots` scale 1.5×; `lines` widen to w-12; `numbers` gain a filled background.
|
|
40
|
-
const INDICATOR_ACTIVE_DOTS = {
|
|
41
|
-
primary: 'bg-primary-solid scale-150',
|
|
42
|
-
secondary: 'bg-secondary-solid scale-150',
|
|
43
|
-
accent: 'bg-accent-solid scale-150',
|
|
44
|
-
neutral: 'bg-neutral-solid scale-150',
|
|
45
|
-
info: 'bg-info-solid scale-150',
|
|
46
|
-
success: 'bg-success-solid scale-150',
|
|
47
|
-
warning: 'bg-warning-solid scale-150',
|
|
48
|
-
error: 'bg-error-solid scale-150',
|
|
49
|
-
};
|
|
50
|
-
const INDICATOR_ACTIVE_LINES = {
|
|
51
|
-
primary: 'bg-primary-solid w-12',
|
|
52
|
-
secondary: 'bg-secondary-solid w-12',
|
|
53
|
-
accent: 'bg-accent-solid w-12',
|
|
54
|
-
neutral: 'bg-neutral-solid w-12',
|
|
55
|
-
info: 'bg-info-solid w-12',
|
|
56
|
-
success: 'bg-success-solid w-12',
|
|
57
|
-
warning: 'bg-warning-solid w-12',
|
|
58
|
-
error: 'bg-error-solid w-12',
|
|
59
|
-
};
|
|
60
|
-
const INDICATOR_ACTIVE_NUMBERS = {
|
|
61
|
-
primary: 'bg-primary-solid text-primary-solid-fg',
|
|
62
|
-
secondary: 'bg-secondary-solid text-secondary-solid-fg',
|
|
63
|
-
accent: 'bg-accent-solid text-accent-solid-fg',
|
|
64
|
-
neutral: 'bg-neutral-solid text-neutral-solid-fg',
|
|
65
|
-
info: 'bg-info-solid text-info-solid-fg',
|
|
66
|
-
success: 'bg-success-solid text-success-solid-fg',
|
|
67
|
-
warning: 'bg-warning-solid text-warning-solid-fg',
|
|
68
|
-
error: 'bg-error-solid text-error-solid-fg',
|
|
69
|
-
};
|
|
70
|
-
const INDICATOR_INACTIVE_DOTS = 'bg-fg-muted opacity-50 hover:opacity-100';
|
|
71
|
-
const INDICATOR_INACTIVE_LINES = 'bg-fg-muted opacity-50 hover:opacity-100';
|
|
72
|
-
const INDICATOR_INACTIVE_NUMBERS = 'bg-surface-muted text-fg hover:bg-surface-sunken';
|
|
73
|
-
function resolveIndicatorActiveClasses(variant, color) {
|
|
74
|
-
switch (variant) {
|
|
75
|
-
case 'dots':
|
|
76
|
-
return INDICATOR_ACTIVE_DOTS[color];
|
|
77
|
-
case 'lines':
|
|
78
|
-
return INDICATOR_ACTIVE_LINES[color];
|
|
79
|
-
case 'numbers':
|
|
80
|
-
return INDICATOR_ACTIVE_NUMBERS[color];
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
function resolveIndicatorInactiveClasses(variant) {
|
|
84
|
-
switch (variant) {
|
|
85
|
-
case 'dots':
|
|
86
|
-
return INDICATOR_INACTIVE_DOTS;
|
|
87
|
-
case 'lines':
|
|
88
|
-
return INDICATOR_INACTIVE_LINES;
|
|
89
|
-
case 'numbers':
|
|
90
|
-
return INDICATOR_INACTIVE_NUMBERS;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
63
|
// ── tv() config ───────────────────────────────────────────────────
|
|
94
64
|
const carouselVariants = tv({
|
|
95
65
|
slots: {
|
|
@@ -114,8 +84,20 @@ const carouselVariants = tv({
|
|
|
114
84
|
'text-white hover:bg-overlay-control-hover transition-colors duration-200 motion-reduce:transition-none ' +
|
|
115
85
|
'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',
|
|
116
86
|
indicators: 'flex items-center justify-center',
|
|
117
|
-
indicator
|
|
87
|
+
// The indicator <button> — the pointer/keyboard target. WCAG 2.2
|
|
88
|
+
// SC 2.5.8 wants 24x24 CSS px and the spacing exception is unavailable
|
|
89
|
+
// (indicators sit in a row, a 24px circle on each would intersect its
|
|
90
|
+
// neighbour). A 12px dot cannot be the target, so the target and the
|
|
91
|
+
// painted mark are two elements: this one is floored at 24x24 at every
|
|
92
|
+
// size and stays transparent; `indicator` below is the visible mark and
|
|
93
|
+
// keeps the whole size axis. Targets wider than the floor (numbers at
|
|
94
|
+
// lg/xl, an active line at `w-12`) grow from the mark inside.
|
|
95
|
+
indicatorTarget: 'inline-flex shrink-0 items-center justify-center min-h-6 min-w-6 cursor-pointer ' +
|
|
118
96
|
'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',
|
|
97
|
+
// The painted mark inside the target. Never focusable — the focus ring
|
|
98
|
+
// lives on `indicatorTarget`, the color transition lives here because
|
|
99
|
+
// this is the element whose `bg-*` changes.
|
|
100
|
+
indicator: 'block transition-colors duration-200 motion-reduce:transition-none',
|
|
119
101
|
},
|
|
120
102
|
variants: {
|
|
121
103
|
orientation: {
|
|
@@ -169,11 +151,18 @@ const carouselVariants = tv({
|
|
|
169
151
|
},
|
|
170
152
|
compoundVariants: [
|
|
171
153
|
// Indicator geometry per variant × size.
|
|
154
|
+
//
|
|
155
|
+
// `dots` follows CLAUDE.md's **dot indicator** sub-scale — 2 / 2.5 / 3 /
|
|
156
|
+
// 3.5 / 4, the five-step 2px cadence `badge-dot` was corrected onto. It
|
|
157
|
+
// previously rendered 2/2.5/3/3/3, freezing md/lg/xl at 12px so two of
|
|
158
|
+
// the five advertised steps were dead on the *default* indicator
|
|
159
|
+
// variant. The active-state `scale-150` is a CSS transform, so it
|
|
160
|
+
// composes multiplicatively with every base value here.
|
|
172
161
|
{ variant: 'dots', size: 'xs', class: { indicator: 'size-2' } },
|
|
173
162
|
{ variant: 'dots', size: 'sm', class: { indicator: 'size-2.5' } },
|
|
174
163
|
{ variant: 'dots', size: 'md', class: { indicator: 'size-3' } },
|
|
175
|
-
{ variant: 'dots', size: 'lg', class: { indicator: 'size-3' } },
|
|
176
|
-
{ variant: 'dots', size: 'xl', class: { indicator: 'size-
|
|
164
|
+
{ variant: 'dots', size: 'lg', class: { indicator: 'size-3.5' } },
|
|
165
|
+
{ variant: 'dots', size: 'xl', class: { indicator: 'size-4' } },
|
|
177
166
|
{ variant: 'lines', size: 'xs', class: { indicator: 'h-1 w-4' } },
|
|
178
167
|
{ variant: 'lines', size: 'sm', class: { indicator: 'h-1 w-5' } },
|
|
179
168
|
{ variant: 'lines', size: 'md', class: { indicator: 'h-1.5 w-6' } },
|
|
@@ -226,7 +215,31 @@ const carouselVariants = tv({
|
|
|
226
215
|
position: 'below',
|
|
227
216
|
},
|
|
228
217
|
}, { twMerge: true });
|
|
218
|
+
|
|
219
|
+
// `CarouselComponent` is the canonical "structural-layout primitive" exception
|
|
220
|
+
// to CLAUDE.md's 5–6 input cap (precedent: `SplitComponent`). The 17 inputs
|
|
221
|
+
// here are each an independent geometry/behavior axis (orientation, slides
|
|
222
|
+
// math, gap, loop, autoplay knobs, drag, keyboard, snap, active index, ARIA
|
|
223
|
+
// label sources, i18n) — removing any would force consumers to coordinate two
|
|
224
|
+
// carousels or replicate logic externally. Documented in
|
|
225
|
+
// docs/requirements/carousel.requirements.md § 2.2 and § 12.
|
|
229
226
|
// ── CarouselSlideComponent ────────────────────────────────────────
|
|
227
|
+
//
|
|
228
|
+
// This class stays in the same file as `CarouselComponent` **on purpose** —
|
|
229
|
+
// do not "finish the split" by moving it out.
|
|
230
|
+
//
|
|
231
|
+
// The two form a true bidirectional dependency: `CarouselComponent` queries
|
|
232
|
+
// the slides with `contentChildren(CarouselSlideComponent)` while every slide
|
|
233
|
+
// resolves its parent with `inject(CarouselComponent)`. Both edges are value
|
|
234
|
+
// edges (a query token and a DI token), so neither is erased at compile time —
|
|
235
|
+
// splitting them across two files produces a circular import at runtime, and
|
|
236
|
+
// whichever module the bundler evaluates second sees `undefined` for the other
|
|
237
|
+
// class. Breaking it needs an injection token or a shared base class first,
|
|
238
|
+
// which is a behavioural change, not a move.
|
|
239
|
+
//
|
|
240
|
+
// The three classes that used to sit below `CarouselComponent` did NOT have
|
|
241
|
+
// this problem — they only inject the parent, never the reverse — and they now
|
|
242
|
+
// live in `carousel-indicators.ts` and `carousel-nav.ts`.
|
|
230
243
|
/**
|
|
231
244
|
* A single slide inside a `<tw-carousel>`. Projects arbitrary content via its
|
|
232
245
|
* default slot. Reports its visibility back to the carousel container via a
|
|
@@ -352,12 +365,10 @@ class CarouselComponent {
|
|
|
352
365
|
/** Two-way bound 0-based index of the first visible slide in the current page. Setting from the parent scrolls the viewport smoothly to align that slide; reading reflects user-driven scroll position after `scrollend`. Defaults to `0`. */
|
|
353
366
|
activeIndex = model(0, /* @ts-ignore */
|
|
354
367
|
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
355
|
-
/** Accessible name for the carousel region. If both this and `
|
|
356
|
-
ariaLabel = input(null, /*
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
ariaLabelledBy = input(null, /* @ts-ignore */
|
|
360
|
-
...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : /* istanbul ignore next */ []));
|
|
368
|
+
/** Accessible name for the carousel region. Mirrored to `aria-label`. If both this and `aria-labelledby` are `null`, a one-time dev-mode `console.warn` is logged (production builds never log). Defaults to `null`. */
|
|
369
|
+
ariaLabel = input(null, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
370
|
+
/** ID of an element labeling the carousel. Mirrored to `aria-labelledby`. Either `aria-label` or `aria-labelledby` SHOULD be provided. Defaults to `null`. */
|
|
371
|
+
ariaLabelledBy = input(null, { ...(ngDevMode ? { debugName: "ariaLabelledBy" } : /* istanbul ignore next */ {}), alias: 'aria-labelledby' });
|
|
361
372
|
/** Localizable strings for prev/next/pause/resume/indicator/slide-of templates. Unset keys fall back to the English defaults in `DEFAULT_CAROUSEL_LABELS`. Defaults to `{}`. */
|
|
362
373
|
labels = input({}, /* @ts-ignore */
|
|
363
374
|
...(ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []));
|
|
@@ -376,11 +387,22 @@ class CarouselComponent {
|
|
|
376
387
|
/** @internal Projected slides in DOM order. */
|
|
377
388
|
slides = contentChildren(CarouselSlideComponent, { ...(ngDevMode ? { debugName: "slides" } : /* istanbul ignore next */ {}), descendants: false });
|
|
378
389
|
// ── Resolved configuration ─────────────────────────────────────
|
|
379
|
-
/**
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
390
|
+
/**
|
|
391
|
+
* @internal Resolved label record with English defaults filled in.
|
|
392
|
+
*
|
|
393
|
+
* Explicitly-undefined keys are dropped before merging. Root `tsconfig.json`
|
|
394
|
+
* does not set `exactOptionalPropertyTypes`, so `[labels]="{ indicator:
|
|
395
|
+
* t('carousel.indicator') }"` type-checks even when `t()` returns
|
|
396
|
+
* `string | undefined` — and a plain spread would then overwrite the default
|
|
397
|
+
* with `undefined`, which reaches `formatLabel()` and throws
|
|
398
|
+
* `Cannot read properties of undefined (reading 'replace')` inside a
|
|
399
|
+
* `computed`, taking the whole render down. Same filter `table.ts` and
|
|
400
|
+
* `timeline.ts` already use; `Required<>` then guarantees a string per key.
|
|
401
|
+
*/
|
|
402
|
+
resolvedLabels = computed(() => {
|
|
403
|
+
const overrides = Object.fromEntries(Object.entries(this.labels() ?? {}).filter(([, value]) => value !== undefined));
|
|
404
|
+
return { ...DEFAULT_CAROUSEL_LABELS, ...overrides };
|
|
405
|
+
}, /* @ts-ignore */
|
|
384
406
|
...(ngDevMode ? [{ debugName: "resolvedLabels" }] : /* istanbul ignore next */ []));
|
|
385
407
|
/** @internal Effective `slidesPerView` clamped to `[0.5, slideCount]`. */
|
|
386
408
|
_effectiveSlidesPerView = computed(() => {
|
|
@@ -514,7 +536,7 @@ class CarouselComponent {
|
|
|
514
536
|
this.ariaLabel() === null &&
|
|
515
537
|
this.ariaLabelledBy() === null) {
|
|
516
538
|
warnedMissingLabel = true;
|
|
517
|
-
console.warn('[tw-carousel] Provide either `
|
|
539
|
+
console.warn('[tw-carousel] Provide either `aria-label` or `aria-labelledby` so the carousel region has an accessible name (WCAG 4.1.2).');
|
|
518
540
|
}
|
|
519
541
|
if (!warnedLowInterval && this.autoplayInterval() < 1000) {
|
|
520
542
|
warnedLowInterval = true;
|
|
@@ -619,6 +641,8 @@ class CarouselComponent {
|
|
|
619
641
|
_onScrollEndBound = null;
|
|
620
642
|
_onScrollDebouncedBound = null;
|
|
621
643
|
_scrollDebounceTimer = null;
|
|
644
|
+
/** Handle for the post-interaction autoplay-pause expiry (see `_onPointerUp`). */
|
|
645
|
+
_postInteractionPauseTimer = null;
|
|
622
646
|
_onVisibilityChangeBound = null;
|
|
623
647
|
_setupViewport() {
|
|
624
648
|
const viewport = this._viewportRef().nativeElement;
|
|
@@ -701,6 +725,10 @@ class CarouselComponent {
|
|
|
701
725
|
this._intersectionObserver = null;
|
|
702
726
|
this._resizeObserver?.disconnect();
|
|
703
727
|
this._resizeObserver = null;
|
|
728
|
+
if (this._postInteractionPauseTimer !== null) {
|
|
729
|
+
clearTimeout(this._postInteractionPauseTimer);
|
|
730
|
+
this._postInteractionPauseTimer = null;
|
|
731
|
+
}
|
|
704
732
|
if (this._loopJumpHandle !== null) {
|
|
705
733
|
clearTimeout(this._loopJumpHandle);
|
|
706
734
|
this._loopJumpHandle = null;
|
|
@@ -1099,7 +1127,14 @@ class CarouselComponent {
|
|
|
1099
1127
|
});
|
|
1100
1128
|
// Post-interaction autoplay pause.
|
|
1101
1129
|
this._postInteractionPauseUntil.set(Date.now() + this._effectiveAutoplayInterval() * 2);
|
|
1102
|
-
|
|
1130
|
+
// Held in a field so `_teardownViewport` can clear it. Unstored, this
|
|
1131
|
+
// fires at least two autoplay intervals after destroy and writes a signal
|
|
1132
|
+
// on a torn-down component.
|
|
1133
|
+
if (this._postInteractionPauseTimer !== null) {
|
|
1134
|
+
clearTimeout(this._postInteractionPauseTimer);
|
|
1135
|
+
}
|
|
1136
|
+
this._postInteractionPauseTimer = setTimeout(() => {
|
|
1137
|
+
this._postInteractionPauseTimer = null;
|
|
1103
1138
|
if (this._postInteractionPauseUntil() !== null &&
|
|
1104
1139
|
Date.now() >= (this._postInteractionPauseUntil() ?? 0)) {
|
|
1105
1140
|
this._postInteractionPauseUntil.set(null);
|
|
@@ -1177,7 +1212,7 @@ class CarouselComponent {
|
|
|
1177
1212
|
this._isManuallyPaused.set(next);
|
|
1178
1213
|
}
|
|
1179
1214
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: CarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1180
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: CarouselComponent, isStandalone: true, selector: "tw-carousel", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, slidesToScroll: { classPropertyName: "slidesToScroll", publicName: "slidesToScroll", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, autoplayInterval: { classPropertyName: "autoplayInterval", publicName: "autoplayInterval", isSignal: true, isRequired: false, transformFunction: null }, pauseOnHover: { classPropertyName: "pauseOnHover", publicName: "pauseOnHover", isSignal: true, isRequired: false, transformFunction: null }, pauseOnFocusIn: { classPropertyName: "pauseOnFocusIn", publicName: "pauseOnFocusIn", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, keyboard: { classPropertyName: "keyboard", publicName: "keyboard", isSignal: true, isRequired: false, transformFunction: null }, snapAlign: { classPropertyName: "snapAlign", publicName: "snapAlign", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "
|
|
1215
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: CarouselComponent, isStandalone: true, selector: "tw-carousel", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, slidesToScroll: { classPropertyName: "slidesToScroll", publicName: "slidesToScroll", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, autoplayInterval: { classPropertyName: "autoplayInterval", publicName: "autoplayInterval", isSignal: true, isRequired: false, transformFunction: null }, pauseOnHover: { classPropertyName: "pauseOnHover", publicName: "pauseOnHover", isSignal: true, isRequired: false, transformFunction: null }, pauseOnFocusIn: { classPropertyName: "pauseOnFocusIn", publicName: "pauseOnFocusIn", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, keyboard: { classPropertyName: "keyboard", publicName: "keyboard", isSignal: true, isRequired: false, transformFunction: null }, snapAlign: { classPropertyName: "snapAlign", publicName: "snapAlign", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange", slideChange: "slideChange", autoplayPaused: "autoplayPaused", autoplayResumed: "autoplayResumed" }, host: { attributes: { "role": "region" }, listeners: { "pointerenter": "_onPointerEnter()", "pointerleave": "_onPointerLeave()", "focusin": "_onFocusIn()", "focusout": "_onFocusOut($event)" }, properties: { "attr.aria-roledescription": "\"carousel\"", "attr.aria-label": "ariaLabel()", "attr.aria-labelledby": "ariaLabelledBy()", "class": "rootClasses()" } }, queries: [{ propertyName: "slides", predicate: CarouselSlideComponent, isSignal: true }], viewQueries: [{ propertyName: "_viewportRef", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1181
1216
|
<div
|
|
1182
1217
|
#viewport
|
|
1183
1218
|
data-tw-carousel-viewport
|
|
@@ -1283,7 +1318,75 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
1283
1318
|
<ng-content />
|
|
1284
1319
|
`,
|
|
1285
1320
|
}]
|
|
1286
|
-
}], ctorParameters: () => [], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], slidesPerView: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidesPerView", required: false }] }], slidesToScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidesToScroll", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], autoplayInterval: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplayInterval", required: false }] }], pauseOnHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "pauseOnHover", required: false }] }], pauseOnFocusIn: [{ type: i0.Input, args: [{ isSignal: true, alias: "pauseOnFocusIn", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], keyboard: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboard", required: false }] }], snapAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapAlign", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "
|
|
1321
|
+
}], ctorParameters: () => [], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], slidesPerView: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidesPerView", required: false }] }], slidesToScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidesToScroll", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], autoplayInterval: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplayInterval", required: false }] }], pauseOnHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "pauseOnHover", required: false }] }], pauseOnFocusIn: [{ type: i0.Input, args: [{ isSignal: true, alias: "pauseOnFocusIn", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], keyboard: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyboard", required: false }] }], snapAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapAlign", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], slideChange: [{ type: i0.Output, args: ["slideChange"] }], autoplayPaused: [{ type: i0.Output, args: ["autoplayPaused"] }], autoplayResumed: [{ type: i0.Output, args: ["autoplayResumed"] }], _viewportRef: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CarouselSlideComponent), { ...{ descendants: false }, isSignal: true }] }] } });
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* `<tw-carousel-indicators>` — the per-page indicator row companion to
|
|
1325
|
+
* `<tw-carousel>`.
|
|
1326
|
+
*
|
|
1327
|
+
* Depends on `CarouselComponent` one-way (it injects the parent; the parent
|
|
1328
|
+
* never references this class), so this file imports `./carousel` and never
|
|
1329
|
+
* the reverse. The static color x state class tables live here because nothing
|
|
1330
|
+
* outside the indicators reads them.
|
|
1331
|
+
*/
|
|
1332
|
+
// ── Static color × state class lookups ──
|
|
1333
|
+
// Tailwind v4 only resolves statically-written class names. Per the stepper
|
|
1334
|
+
// precedent, every color × active/inactive indicator combination is enumerated.
|
|
1335
|
+
// Active indicators are also distinguishable by more than color (WCAG 1.4.1):
|
|
1336
|
+
// `dots` scale 1.5×; `lines` widen to w-12; `numbers` gain a filled background.
|
|
1337
|
+
const INDICATOR_ACTIVE_DOTS = {
|
|
1338
|
+
primary: 'bg-primary-solid scale-150',
|
|
1339
|
+
secondary: 'bg-secondary-solid scale-150',
|
|
1340
|
+
accent: 'bg-accent-solid scale-150',
|
|
1341
|
+
neutral: 'bg-neutral-solid scale-150',
|
|
1342
|
+
info: 'bg-info-solid scale-150',
|
|
1343
|
+
success: 'bg-success-solid scale-150',
|
|
1344
|
+
warning: 'bg-warning-solid scale-150',
|
|
1345
|
+
error: 'bg-error-solid scale-150',
|
|
1346
|
+
};
|
|
1347
|
+
const INDICATOR_ACTIVE_LINES = {
|
|
1348
|
+
primary: 'bg-primary-solid w-12',
|
|
1349
|
+
secondary: 'bg-secondary-solid w-12',
|
|
1350
|
+
accent: 'bg-accent-solid w-12',
|
|
1351
|
+
neutral: 'bg-neutral-solid w-12',
|
|
1352
|
+
info: 'bg-info-solid w-12',
|
|
1353
|
+
success: 'bg-success-solid w-12',
|
|
1354
|
+
warning: 'bg-warning-solid w-12',
|
|
1355
|
+
error: 'bg-error-solid w-12',
|
|
1356
|
+
};
|
|
1357
|
+
const INDICATOR_ACTIVE_NUMBERS = {
|
|
1358
|
+
primary: 'bg-primary-solid text-primary-solid-fg',
|
|
1359
|
+
secondary: 'bg-secondary-solid text-secondary-solid-fg',
|
|
1360
|
+
accent: 'bg-accent-solid text-accent-solid-fg',
|
|
1361
|
+
neutral: 'bg-neutral-solid text-neutral-solid-fg',
|
|
1362
|
+
info: 'bg-info-solid text-info-solid-fg',
|
|
1363
|
+
success: 'bg-success-solid text-success-solid-fg',
|
|
1364
|
+
warning: 'bg-warning-solid text-warning-solid-fg',
|
|
1365
|
+
error: 'bg-error-solid text-error-solid-fg',
|
|
1366
|
+
};
|
|
1367
|
+
const INDICATOR_INACTIVE_DOTS = 'bg-fg-muted opacity-50 hover:opacity-100';
|
|
1368
|
+
const INDICATOR_INACTIVE_LINES = 'bg-fg-muted opacity-50 hover:opacity-100';
|
|
1369
|
+
const INDICATOR_INACTIVE_NUMBERS = 'bg-surface-muted text-fg hover:bg-surface-sunken';
|
|
1370
|
+
function resolveIndicatorActiveClasses(variant, color) {
|
|
1371
|
+
switch (variant) {
|
|
1372
|
+
case 'dots':
|
|
1373
|
+
return INDICATOR_ACTIVE_DOTS[color];
|
|
1374
|
+
case 'lines':
|
|
1375
|
+
return INDICATOR_ACTIVE_LINES[color];
|
|
1376
|
+
case 'numbers':
|
|
1377
|
+
return INDICATOR_ACTIVE_NUMBERS[color];
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
function resolveIndicatorInactiveClasses(variant) {
|
|
1381
|
+
switch (variant) {
|
|
1382
|
+
case 'dots':
|
|
1383
|
+
return INDICATOR_INACTIVE_DOTS;
|
|
1384
|
+
case 'lines':
|
|
1385
|
+
return INDICATOR_INACTIVE_LINES;
|
|
1386
|
+
case 'numbers':
|
|
1387
|
+
return INDICATOR_INACTIVE_NUMBERS;
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1287
1390
|
// ── CarouselIndicatorsComponent ───────────────────────────────────
|
|
1288
1391
|
/**
|
|
1289
1392
|
* Renders one button per **page** (not per slide) inside a `<tw-carousel>`.
|
|
@@ -1346,7 +1449,11 @@ class CarouselIndicatorsComponent {
|
|
|
1346
1449
|
});
|
|
1347
1450
|
}
|
|
1348
1451
|
}
|
|
1349
|
-
|
|
1452
|
+
/** @internal Classes for the indicator `<button>` — the 24x24-floored hit target (SC 2.5.8). Identical for every page, so it is a computed rather than a per-page call. */
|
|
1453
|
+
_buttonClasses = computed(() => this._variantResult().indicatorTarget(), /* @ts-ignore */
|
|
1454
|
+
...(ngDevMode ? [{ debugName: "_buttonClasses" }] : /* istanbul ignore next */ []));
|
|
1455
|
+
/** @internal Classes for the painted mark inside the target: geometry from the `variant` × `size` compound variants, fill from the active/inactive lookup. */
|
|
1456
|
+
_indicatorClasses(page) {
|
|
1350
1457
|
const base = this._variantResult().indicator();
|
|
1351
1458
|
const active = page === this.carousel.activePage();
|
|
1352
1459
|
const stateClasses = active
|
|
@@ -1370,14 +1477,16 @@ class CarouselIndicatorsComponent {
|
|
|
1370
1477
|
@for (page of _pages(); track page) {
|
|
1371
1478
|
<button
|
|
1372
1479
|
type="button"
|
|
1373
|
-
[class]="_buttonClasses(
|
|
1480
|
+
[class]="_buttonClasses()"
|
|
1374
1481
|
[attr.aria-label]="_buttonLabel(page)"
|
|
1375
1482
|
[attr.aria-current]="page === carousel.activePage() ? 'true' : null"
|
|
1376
1483
|
(click)="_onClick(page)"
|
|
1377
1484
|
>
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1485
|
+
<span [class]="_indicatorClasses(page)">
|
|
1486
|
+
@if (variant() === 'numbers') {
|
|
1487
|
+
{{ page + 1 }}
|
|
1488
|
+
}
|
|
1489
|
+
</span>
|
|
1381
1490
|
</button>
|
|
1382
1491
|
}
|
|
1383
1492
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -1395,19 +1504,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
1395
1504
|
@for (page of _pages(); track page) {
|
|
1396
1505
|
<button
|
|
1397
1506
|
type="button"
|
|
1398
|
-
[class]="_buttonClasses(
|
|
1507
|
+
[class]="_buttonClasses()"
|
|
1399
1508
|
[attr.aria-label]="_buttonLabel(page)"
|
|
1400
1509
|
[attr.aria-current]="page === carousel.activePage() ? 'true' : null"
|
|
1401
1510
|
(click)="_onClick(page)"
|
|
1402
1511
|
>
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1512
|
+
<span [class]="_indicatorClasses(page)">
|
|
1513
|
+
@if (variant() === 'numbers') {
|
|
1514
|
+
{{ page + 1 }}
|
|
1515
|
+
}
|
|
1516
|
+
</span>
|
|
1406
1517
|
</button>
|
|
1407
1518
|
}
|
|
1408
1519
|
`,
|
|
1409
1520
|
}]
|
|
1410
1521
|
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }] } });
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
* `[twCarouselPrev]` / `[twCarouselNext]` — the prev/next navigation
|
|
1525
|
+
* directives applied to a consumer's own button primitive.
|
|
1526
|
+
*
|
|
1527
|
+
* Both inject `CarouselComponent` and are never referenced by it, so the
|
|
1528
|
+
* import edge to `./carousel` is strictly one-way.
|
|
1529
|
+
*/
|
|
1411
1530
|
// ── Prev / Next directives ────────────────────────────────────────
|
|
1412
1531
|
/**
|
|
1413
1532
|
* Apply to any focusable element (typically `<button>`) inside a `<tw-carousel>`
|