@egose/shadcn-theme-ng-tw 0.0.28 → 0.2.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 +130 -13
- package/accordion/README.md +376 -34
- package/accordion/fesm2022/accordion.mjs +20 -20
- package/alert/README.md +343 -34
- package/alert/fesm2022/alert.mjs +18 -18
- package/alert-dialog/README.md +471 -5
- package/alert-dialog/fesm2022/alert-dialog.mjs +48 -48
- package/alert-dialog/types/alert-dialog.d.ts +1 -1
- package/aspect-ratio/README.md +272 -5
- package/aspect-ratio/fesm2022/aspect-ratio.mjs +9 -9
- package/autocomplete/README.md +473 -34
- package/autocomplete/fesm2022/autocomplete.mjs +54 -54
- package/autocomplete/types/autocomplete.d.ts +1 -1
- package/avatar/README.md +357 -5
- package/avatar/fesm2022/avatar.mjs +32 -32
- package/badge/README.md +289 -34
- package/badge/fesm2022/badge.mjs +4 -4
- package/basic-alert/README.md +324 -34
- package/basic-alert/fesm2022/basic-alert.mjs +4 -4
- package/basic-alert/types/basic-alert.d.ts +1 -1
- package/breadcrumb/README.md +406 -5
- package/breadcrumb/fesm2022/breadcrumb.mjs +34 -34
- package/button/README.md +453 -34
- package/button/fesm2022/button.mjs +96 -118
- package/button/types/button.d.ts +7 -10
- package/button-group/README.md +318 -5
- package/button-group/fesm2022/button-group.mjs +20 -20
- package/calendar/README.md +328 -34
- package/calendar/fesm2022/calendar.mjs +154 -154
- package/card/README.md +331 -5
- package/card/fesm2022/card.mjs +33 -33
- package/carousel/README.md +333 -5
- package/carousel/fesm2022/carousel.mjs +47 -44
- package/carousel/types/carousel.d.ts +1 -1
- package/checkbox/README.md +291 -34
- package/checkbox/fesm2022/checkbox.mjs +22 -20
- package/checkbox/types/checkbox.d.ts +5 -4
- package/collapsible/README.md +332 -5
- package/collapsible/fesm2022/collapsible.mjs +15 -15
- package/combobox/README.md +507 -5
- package/combobox/fesm2022/combobox.mjs +95 -92
- package/combobox/types/combobox.d.ts +1 -1
- package/command/README.md +435 -5
- package/command/fesm2022/command.mjs +56 -56
- package/confirmation-dialog/README.md +272 -34
- package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +13 -12
- package/confirmation-dialog/types/confirmation-dialog.d.ts +9 -5
- package/context-menu/README.md +366 -5
- package/context-menu/fesm2022/context-menu.mjs +9 -9
- package/date-picker/README.md +436 -34
- package/date-picker/fesm2022/date-picker.mjs +79 -68
- package/date-picker/types/date-picker.d.ts +8 -4
- package/dialog/README.md +419 -34
- package/dialog/fesm2022/dialog.mjs +48 -48
- package/drawer/README.md +395 -5
- package/drawer/fesm2022/drawer.mjs +45 -45
- package/dropdown-menu/README.md +417 -5
- package/dropdown-menu/fesm2022/dropdown-menu.mjs +85 -73
- package/dropdown-menu/types/dropdown-menu.d.ts +4 -0
- package/empty/README.md +329 -5
- package/empty/fesm2022/empty.mjs +31 -31
- package/field/README.md +385 -5
- package/field/fesm2022/field.mjs +59 -59
- package/field/types/field.d.ts +1 -1
- package/form-checkbox/README.md +283 -34
- package/form-checkbox/fesm2022/form-checkbox.mjs +37 -19
- package/form-checkbox/types/form-checkbox.d.ts +7 -1
- package/form-date-picker/README.md +293 -34
- package/form-date-picker/fesm2022/form-date-picker.mjs +59 -24
- package/form-date-picker/types/form-date-picker.d.ts +7 -1
- package/form-field/README.md +327 -34
- package/form-field/fesm2022/form-field.mjs +30 -16
- package/form-field/types/form-field.d.ts +28 -20
- package/form-field-simple/README.md +311 -34
- package/form-field-simple/fesm2022/form-field-simple.mjs +4 -4
- package/form-searchable-multiselect/README.md +332 -34
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +41 -21
- package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +8 -2
- package/form-select/README.md +321 -34
- package/form-select/fesm2022/form-select.mjs +62 -29
- package/form-select/types/form-select.d.ts +7 -1
- package/form-text-input/README.md +342 -34
- package/form-text-input/fesm2022/form-text-input.mjs +43 -55
- package/form-text-input/types/form-text-input.d.ts +9 -12
- package/form-textarea/README.md +318 -34
- package/form-textarea/fesm2022/form-textarea.mjs +42 -23
- package/form-textarea/types/form-textarea.d.ts +8 -1
- package/hover-card/README.md +256 -5
- package/hover-card/fesm2022/hover-card.mjs +19 -19
- package/icon/README.md +210 -34
- package/icon/fesm2022/icon.mjs +8 -8
- package/input/README.md +240 -34
- package/input/fesm2022/input.mjs +17 -12
- package/input/types/input.d.ts +2 -1
- package/input-group/README.md +335 -5
- package/input-group/fesm2022/input-group.mjs +37 -37
- package/input-group/types/input-group.d.ts +3 -3
- package/input-otp/README.md +375 -5
- package/input-otp/fesm2022/input-otp.mjs +27 -27
- package/item/README.md +385 -5
- package/item/fesm2022/item.mjs +54 -54
- package/kbd/README.md +291 -5
- package/kbd/fesm2022/kbd.mjs +13 -13
- package/label/README.md +243 -34
- package/label/fesm2022/label.mjs +9 -9
- package/label/types/label.d.ts +1 -1
- package/layout-simple/README.md +174 -44
- package/layout-simple/fesm2022/layout-simple.mjs +917 -398
- package/layout-simple/types/layout-simple.d.ts +180 -129
- package/menu/README.md +418 -0
- package/menu/fesm2022/menu.mjs +461 -0
- package/menu/package.json +24 -0
- package/menu/types/menu.d.ts +137 -0
- package/menubar/README.md +343 -5
- package/menubar/fesm2022/menubar.mjs +13 -13
- package/native-select/README.md +323 -5
- package/native-select/fesm2022/native-select.mjs +19 -19
- package/navigation-menu/README.md +369 -5
- package/navigation-menu/fesm2022/navigation-menu.mjs +37 -37
- package/package.json +183 -154
- package/pagination/README.md +388 -5
- package/pagination/fesm2022/pagination.mjs +63 -63
- package/popover/README.md +302 -34
- package/popover/fesm2022/popover.mjs +30 -30
- package/progress/README.md +311 -5
- package/progress/fesm2022/progress.mjs +13 -13
- package/radio-group/README.md +335 -34
- package/radio-group/fesm2022/radio-group.mjs +26 -19
- package/resizable/README.md +269 -5
- package/resizable/fesm2022/resizable.mjs +19 -19
- package/scroll-area/README.md +233 -5
- package/scroll-area/fesm2022/scroll-area.mjs +9 -9
- package/searchable-multiselect/README.md +294 -34
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +63 -16
- package/searchable-multiselect/types/searchable-multiselect.d.ts +8 -2
- package/select/README.md +408 -34
- package/select/fesm2022/select.mjs +80 -72
- package/select/types/select.d.ts +3 -1
- package/separator/README.md +193 -34
- package/separator/fesm2022/separator.mjs +9 -9
- package/separator/types/separator.d.ts +1 -1
- package/sheet/README.md +282 -34
- package/sheet/fesm2022/sheet.mjs +30 -30
- package/sidebar/README.md +457 -5
- package/sidebar/fesm2022/sidebar.mjs +136 -134
- package/sidebar/types/sidebar.d.ts +3 -3
- package/skeleton/README.md +217 -5
- package/skeleton/fesm2022/skeleton.mjs +9 -9
- package/slider/README.md +273 -5
- package/slider/fesm2022/slider.mjs +29 -25
- package/sonner/README.md +317 -34
- package/sonner/fesm2022/sonner.mjs +9 -9
- package/spinner/README.md +255 -34
- package/spinner/fesm2022/spinner.mjs +8 -8
- package/switch/README.md +281 -34
- package/switch/fesm2022/switch.mjs +12 -14
- package/table/README.md +423 -5
- package/table/fesm2022/table.mjs +41 -41
- package/tabs/README.md +382 -34
- package/tabs/fesm2022/tabs.mjs +48 -38
- package/textarea/README.md +282 -5
- package/textarea/fesm2022/textarea.mjs +9 -9
- package/toggle/README.md +270 -5
- package/toggle/fesm2022/toggle.mjs +14 -14
- package/toggle-group/README.md +340 -5
- package/toggle-group/fesm2022/toggle-group.mjs +13 -13
- package/toggle-group/types/toggle-group.d.ts +13 -7
- package/tooltip/README.md +240 -34
- package/tooltip/fesm2022/tooltip.mjs +14 -14
- package/typography/README.md +271 -5
- package/typography/fesm2022/typography.mjs +53 -53
- package/typography/types/typography.d.ts +12 -12
- package/utils/README.md +274 -34
- package/utils/fesm2022/utils.mjs +68 -44
- package/accordion/fesm2022/accordion.mjs.map +0 -1
- package/alert/fesm2022/alert.mjs.map +0 -1
- package/alert-dialog/fesm2022/alert-dialog.mjs.map +0 -1
- package/aspect-ratio/fesm2022/aspect-ratio.mjs.map +0 -1
- package/autocomplete/fesm2022/autocomplete.mjs.map +0 -1
- package/avatar/fesm2022/avatar.mjs.map +0 -1
- package/badge/fesm2022/badge.mjs.map +0 -1
- package/basic-alert/fesm2022/basic-alert.mjs.map +0 -1
- package/breadcrumb/fesm2022/breadcrumb.mjs.map +0 -1
- package/button/fesm2022/button.mjs.map +0 -1
- package/button-group/fesm2022/button-group.mjs.map +0 -1
- package/calendar/fesm2022/calendar.mjs.map +0 -1
- package/card/fesm2022/card.mjs.map +0 -1
- package/carousel/fesm2022/carousel.mjs.map +0 -1
- package/checkbox/fesm2022/checkbox.mjs.map +0 -1
- package/collapsible/fesm2022/collapsible.mjs.map +0 -1
- package/combobox/fesm2022/combobox.mjs.map +0 -1
- package/command/fesm2022/command.mjs.map +0 -1
- package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +0 -1
- package/context-menu/fesm2022/context-menu.mjs.map +0 -1
- package/date-picker/fesm2022/date-picker.mjs.map +0 -1
- package/dialog/fesm2022/dialog.mjs.map +0 -1
- package/drawer/fesm2022/drawer.mjs.map +0 -1
- package/dropdown-menu/fesm2022/dropdown-menu.mjs.map +0 -1
- package/empty/fesm2022/empty.mjs.map +0 -1
- package/field/fesm2022/field.mjs.map +0 -1
- package/form-checkbox/fesm2022/form-checkbox.mjs.map +0 -1
- package/form-date-picker/fesm2022/form-date-picker.mjs.map +0 -1
- package/form-field/fesm2022/form-field.mjs.map +0 -1
- package/form-field-simple/fesm2022/form-field-simple.mjs.map +0 -1
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +0 -1
- package/form-select/fesm2022/form-select.mjs.map +0 -1
- package/form-text-input/fesm2022/form-text-input.mjs.map +0 -1
- package/form-textarea/fesm2022/form-textarea.mjs.map +0 -1
- package/hover-card/fesm2022/hover-card.mjs.map +0 -1
- package/icon/fesm2022/icon.mjs.map +0 -1
- package/input/fesm2022/input.mjs.map +0 -1
- package/input-group/fesm2022/input-group.mjs.map +0 -1
- package/input-otp/fesm2022/input-otp.mjs.map +0 -1
- package/item/fesm2022/item.mjs.map +0 -1
- package/kbd/fesm2022/kbd.mjs.map +0 -1
- package/label/fesm2022/label.mjs.map +0 -1
- package/layout-simple/fesm2022/layout-simple.mjs.map +0 -1
- package/menubar/fesm2022/menubar.mjs.map +0 -1
- package/native-select/fesm2022/native-select.mjs.map +0 -1
- package/navigation-menu/fesm2022/navigation-menu.mjs.map +0 -1
- package/pagination/fesm2022/pagination.mjs.map +0 -1
- package/popover/fesm2022/popover.mjs.map +0 -1
- package/progress/fesm2022/progress.mjs.map +0 -1
- package/radio-group/fesm2022/radio-group.mjs.map +0 -1
- package/resizable/fesm2022/resizable.mjs.map +0 -1
- package/scroll-area/fesm2022/scroll-area.mjs.map +0 -1
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs.map +0 -1
- package/select/fesm2022/select.mjs.map +0 -1
- package/separator/fesm2022/separator.mjs.map +0 -1
- package/sheet/fesm2022/sheet.mjs.map +0 -1
- package/sidebar/fesm2022/sidebar.mjs.map +0 -1
- package/skeleton/fesm2022/skeleton.mjs.map +0 -1
- package/slider/fesm2022/slider.mjs.map +0 -1
- package/sonner/fesm2022/sonner.mjs.map +0 -1
- package/spinner/fesm2022/spinner.mjs.map +0 -1
- package/switch/fesm2022/switch.mjs.map +0 -1
- package/table/fesm2022/table.mjs.map +0 -1
- package/tabs/fesm2022/tabs.mjs.map +0 -1
- package/textarea/fesm2022/textarea.mjs.map +0 -1
- package/toggle/fesm2022/toggle.mjs.map +0 -1
- package/toggle-group/fesm2022/toggle-group.mjs.map +0 -1
- package/tooltip/fesm2022/tooltip.mjs.map +0 -1
- package/typography/fesm2022/typography.mjs.map +0 -1
- package/utils/fesm2022/utils.mjs.map +0 -1
package/tabs/fesm2022/tabs.mjs
CHANGED
|
@@ -14,12 +14,12 @@ class HlmTabs {
|
|
|
14
14
|
tab = input.required(/* @ts-ignore */
|
|
15
15
|
...(ngDevMode ? [{ debugName: "tab" }] : /* istanbul ignore next */ []));
|
|
16
16
|
constructor() {
|
|
17
|
-
classes(() => 'group/tabs flex gap-2 data-[orientation=horizontal]:flex-col');
|
|
17
|
+
classes(() => 'tw:group/tabs tw:flex tw:gap-2 tw:data-[orientation=horizontal]:flex-col');
|
|
18
18
|
}
|
|
19
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
20
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.
|
|
19
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabs, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
20
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmTabs, isStandalone: true, selector: "[hlmTabs],hlm-tabs", inputs: { tab: { classPropertyName: "tab", publicName: "tab", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "data-slot": "tabs" } }, hostDirectives: [{ directive: i1.BrnTabs, inputs: ["orientation", "orientation", "activationMode", "activationMode", "brnTabs", "tab"], outputs: ["tabActivated", "tabActivated"] }], ngImport: i0 });
|
|
21
21
|
}
|
|
22
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
22
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabs, decorators: [{
|
|
23
23
|
type: Directive,
|
|
24
24
|
args: [{
|
|
25
25
|
selector: '[hlmTabs],hlm-tabs',
|
|
@@ -39,12 +39,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
39
39
|
class HlmTabsContent {
|
|
40
40
|
contentFor = input.required({ ...(ngDevMode ? { debugName: "contentFor" } : /* istanbul ignore next */ {}), alias: 'hlmTabsContent' });
|
|
41
41
|
constructor() {
|
|
42
|
-
classes(() => 'flex-1 text-sm outline-none');
|
|
42
|
+
classes(() => 'tw:flex-1 tw:text-sm tw:outline-none');
|
|
43
43
|
}
|
|
44
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
45
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.
|
|
44
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
45
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmTabsContent, isStandalone: true, selector: "[hlmTabsContent]", inputs: { contentFor: { classPropertyName: "contentFor", publicName: "hlmTabsContent", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "data-slot": "tabs-content" } }, hostDirectives: [{ directive: i1.BrnTabsContent, inputs: ["brnTabsContent", "hlmTabsContent"] }], ngImport: i0 });
|
|
46
46
|
}
|
|
47
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
47
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsContent, decorators: [{
|
|
48
48
|
type: Directive,
|
|
49
49
|
args: [{
|
|
50
50
|
selector: '[hlmTabsContent]',
|
|
@@ -56,10 +56,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
56
56
|
}], ctorParameters: () => [], propDecorators: { contentFor: [{ type: i0.Input, args: [{ isSignal: true, alias: "hlmTabsContent", required: true }] }] } });
|
|
57
57
|
|
|
58
58
|
class HlmTabsContentLazy {
|
|
59
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
60
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.
|
|
59
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsContentLazy, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
60
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmTabsContentLazy, isStandalone: true, selector: "ng-template[hlmTabsContentLazy]", hostDirectives: [{ directive: i1.BrnTabsContentLazy }], ngImport: i0 });
|
|
61
61
|
}
|
|
62
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
62
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsContentLazy, decorators: [{
|
|
63
63
|
type: Directive,
|
|
64
64
|
args: [{
|
|
65
65
|
selector: 'ng-template[hlmTabsContentLazy]',
|
|
@@ -67,11 +67,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
67
67
|
}]
|
|
68
68
|
}] });
|
|
69
69
|
|
|
70
|
-
const listVariants = cva('rounded-lg p-[3px] group-data-horizontal/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col', {
|
|
70
|
+
const listVariants = cva('tw:rounded-lg tw:p-[3px] tw:group-data-horizontal/tabs:h-9 tw:data-[variant=line]:rounded-none tw:group/tabs-list tw:text-muted-foreground tw:inline-flex tw:w-fit tw:items-center tw:justify-center tw:group-data-[orientation=vertical]/tabs:h-fit tw:group-data-[orientation=vertical]/tabs:flex-col', {
|
|
71
71
|
variants: {
|
|
72
72
|
variant: {
|
|
73
|
-
default: 'bg-muted',
|
|
74
|
-
line: 'gap-1 bg-transparent',
|
|
73
|
+
default: 'tw:bg-muted',
|
|
74
|
+
line: 'tw:gap-1 tw:bg-transparent',
|
|
75
75
|
},
|
|
76
76
|
},
|
|
77
77
|
defaultVariants: {
|
|
@@ -84,10 +84,10 @@ class HlmTabsList {
|
|
|
84
84
|
constructor() {
|
|
85
85
|
classes(() => listVariants({ variant: this.variant() }));
|
|
86
86
|
}
|
|
87
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
88
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.
|
|
87
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsList, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
88
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmTabsList, isStandalone: true, selector: "[hlmTabsList],hlm-tabs-list", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "tabs-list" }, properties: { "attr.data-variant": "variant()" } }, hostDirectives: [{ directive: i1.BrnTabsList }], ngImport: i0 });
|
|
89
89
|
}
|
|
90
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
90
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsList, decorators: [{
|
|
91
91
|
type: Directive,
|
|
92
92
|
args: [{
|
|
93
93
|
selector: '[hlmTabsList],hlm-tabs-list',
|
|
@@ -102,7 +102,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
102
102
|
class HlmTabsPaginatedList extends BrnTabsPaginatedList {
|
|
103
103
|
constructor() {
|
|
104
104
|
super();
|
|
105
|
-
classes(() => 'relative flex flex-shrink-0 items-center gap-1 overflow-hidden');
|
|
105
|
+
classes(() => 'tw:relative tw:flex tw:flex-shrink-0 tw:items-center tw:gap-1 tw:overflow-hidden');
|
|
106
106
|
}
|
|
107
107
|
items = contentChildren(BrnTabsTrigger, { ...(ngDevMode ? { debugName: "items" } : /* istanbul ignore next */ {}), descendants: false });
|
|
108
108
|
/** Explicitly annotating type to avoid non-portable inferred type */
|
|
@@ -122,13 +122,13 @@ class HlmTabsPaginatedList extends BrnTabsPaginatedList {
|
|
|
122
122
|
...(ngDevMode ? [{ debugName: "_tabListClass" }] : /* istanbul ignore next */ []));
|
|
123
123
|
paginationButtonClass = input('', /* @ts-ignore */
|
|
124
124
|
...(ngDevMode ? [{ debugName: "paginationButtonClass" }] : /* istanbul ignore next */ []));
|
|
125
|
-
_paginationButtonClass = computed(() => hlm('relative z-[2] select-none disabled:cursor-default', buttonVariants({ variant: 'ghost', size: 'icon-sm' }), this.paginationButtonClass(), this.showPaginationControls() ? 'inline-flex' : 'hidden'), /* @ts-ignore */
|
|
125
|
+
_paginationButtonClass = computed(() => hlm('tw:relative tw:z-[2] tw:select-none tw:disabled:cursor-default', buttonVariants({ variant: 'ghost', size: 'icon-sm' }), this.paginationButtonClass(), this.showPaginationControls() ? 'tw:inline-flex' : 'tw:hidden'), /* @ts-ignore */
|
|
126
126
|
...(ngDevMode ? [{ debugName: "_paginationButtonClass" }] : /* istanbul ignore next */ []));
|
|
127
127
|
_itemSelected(event) {
|
|
128
128
|
event.preventDefault();
|
|
129
129
|
}
|
|
130
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
131
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.
|
|
130
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsPaginatedList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
131
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmTabsPaginatedList, isStandalone: true, selector: "hlm-paginated-tabs-list", inputs: { tabListClass: { classPropertyName: "tabListClass", publicName: "tabListClass", isSignal: true, isRequired: false, transformFunction: null }, paginationButtonClass: { classPropertyName: "paginationButtonClass", publicName: "paginationButtonClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "tabs-paginated-list" } }, providers: [provideIcons({ lucideChevronRight, lucideChevronLeft })], queries: [{ propertyName: "items", predicate: BrnTabsTrigger, isSignal: true }], viewQueries: [{ propertyName: "tabListContainer", first: true, predicate: ["tabListContainer"], descendants: true, isSignal: true }, { propertyName: "tabList", first: true, predicate: ["tabList"], descendants: true, isSignal: true }, { propertyName: "tabListInner", first: true, predicate: ["tabListInner"], descendants: true, isSignal: true }, { propertyName: "nextPaginator", first: true, predicate: ["nextPaginator"], descendants: true, isSignal: true }, { propertyName: "previousPaginator", first: true, predicate: ["previousPaginator"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
132
132
|
<button
|
|
133
133
|
#previousPaginator
|
|
134
134
|
data-pagination="previous"
|
|
@@ -144,8 +144,13 @@ class HlmTabsPaginatedList extends BrnTabsPaginatedList {
|
|
|
144
144
|
<ng-icon name="lucideChevronLeft" />
|
|
145
145
|
</button>
|
|
146
146
|
|
|
147
|
-
<div #tabListContainer class="z-[1] flex grow overflow-hidden" (keydown)="_handleKeydown($event)">
|
|
148
|
-
<div
|
|
147
|
+
<div #tabListContainer class="tw:z-[1] tw:flex tw:grow tw:overflow-hidden" (keydown)="_handleKeydown($event)">
|
|
148
|
+
<div
|
|
149
|
+
class="tw:relative tw:grow tw:transition-transform"
|
|
150
|
+
#tabList
|
|
151
|
+
role="tablist"
|
|
152
|
+
(cdkObserveContent)="_onContentChanges()"
|
|
153
|
+
>
|
|
149
154
|
<div #tabListInner [class]="_tabListClass()">
|
|
150
155
|
<ng-content />
|
|
151
156
|
</div>
|
|
@@ -168,7 +173,7 @@ class HlmTabsPaginatedList extends BrnTabsPaginatedList {
|
|
|
168
173
|
</button>
|
|
169
174
|
`, isInline: true, dependencies: [{ kind: "directive", type: CdkObserveContent, selector: "[cdkObserveContent]", inputs: ["cdkObserveContentDisabled", "debounce"], outputs: ["cdkObserveContent"], exportAs: ["cdkObserveContent"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
170
175
|
}
|
|
171
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
176
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsPaginatedList, decorators: [{
|
|
172
177
|
type: Component,
|
|
173
178
|
args: [{
|
|
174
179
|
selector: 'hlm-paginated-tabs-list',
|
|
@@ -194,8 +199,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
194
199
|
<ng-icon name="lucideChevronLeft" />
|
|
195
200
|
</button>
|
|
196
201
|
|
|
197
|
-
<div #tabListContainer class="z-[1] flex grow overflow-hidden" (keydown)="_handleKeydown($event)">
|
|
198
|
-
<div
|
|
202
|
+
<div #tabListContainer class="tw:z-[1] tw:flex tw:grow tw:overflow-hidden" (keydown)="_handleKeydown($event)">
|
|
203
|
+
<div
|
|
204
|
+
class="tw:relative tw:grow tw:transition-transform"
|
|
205
|
+
#tabList
|
|
206
|
+
role="tablist"
|
|
207
|
+
(cdkObserveContent)="_onContentChanges()"
|
|
208
|
+
>
|
|
199
209
|
<div #tabListInner [class]="_tabListClass()">
|
|
200
210
|
<ng-content />
|
|
201
211
|
</div>
|
|
@@ -224,16 +234,16 @@ class HlmTabsTrigger {
|
|
|
224
234
|
triggerFor = input.required({ ...(ngDevMode ? { debugName: "triggerFor" } : /* istanbul ignore next */ {}), alias: 'hlmTabsTrigger' });
|
|
225
235
|
constructor() {
|
|
226
236
|
classes(() => [
|
|
227
|
-
`gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_ng-icon:not([class*='text-'])]:text-[length:--spacing(4)] focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0`,
|
|
228
|
-
'group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent',
|
|
229
|
-
'data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground',
|
|
230
|
-
'after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100',
|
|
237
|
+
`tw:gap-1.5 tw:rounded-md tw:border tw:border-transparent tw:px-2 tw:py-1 tw:text-sm tw:font-medium tw:group-data-[variant=default]/tabs-list:data-active:shadow-sm tw:group-data-[variant=line]/tabs-list:data-active:shadow-none tw:[&_ng-icon:not([class*='text-'])]:text-[length:--spacing(4)] tw:focus-visible:border-ring tw:focus-visible:ring-ring/50 tw:focus-visible:outline-ring tw:text-foreground/60 tw:hover:text-foreground tw:dark:text-muted-foreground tw:dark:hover:text-foreground tw:relative tw:inline-flex tw:h-[calc(100%-1px)] tw:flex-1 tw:items-center tw:justify-center tw:whitespace-nowrap tw:transition-all tw:group-data-[orientation=vertical]/tabs:w-full tw:group-data-[orientation=vertical]/tabs:justify-start tw:focus-visible:ring-[3px] tw:focus-visible:outline-1 tw:disabled:pointer-events-none tw:disabled:opacity-50 tw:[&_ng-icon]:pointer-events-none tw:[&_ng-icon]:shrink-0`,
|
|
238
|
+
'tw:group-data-[variant=line]/tabs-list:bg-transparent tw:group-data-[variant=line]/tabs-list:data-active:bg-transparent tw:dark:group-data-[variant=line]/tabs-list:data-active:border-transparent tw:dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent',
|
|
239
|
+
'tw:data-active:bg-background tw:dark:data-active:text-foreground tw:dark:data-active:border-input tw:dark:data-active:bg-input/30 tw:data-active:text-foreground',
|
|
240
|
+
'tw:after:bg-foreground tw:after:absolute tw:after:opacity-0 tw:after:transition-opacity tw:group-data-[orientation=horizontal]/tabs:after:inset-x-0 tw:group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] tw:group-data-[orientation=horizontal]/tabs:after:h-0.5 tw:group-data-[orientation=vertical]/tabs:after:inset-y-0 tw:group-data-[orientation=vertical]/tabs:after:-right-1 tw:group-data-[orientation=vertical]/tabs:after:w-0.5 tw:group-data-[variant=line]/tabs-list:data-active:after:opacity-100',
|
|
231
241
|
]);
|
|
232
242
|
}
|
|
233
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
234
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.
|
|
243
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
244
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmTabsTrigger, isStandalone: true, selector: "[hlmTabsTrigger]", inputs: { triggerFor: { classPropertyName: "triggerFor", publicName: "hlmTabsTrigger", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "data-slot": "tabs-trigger" } }, hostDirectives: [{ directive: i1.BrnTabsTrigger, inputs: ["brnTabsTrigger", "hlmTabsTrigger", "disabled", "disabled"] }], ngImport: i0 });
|
|
235
245
|
}
|
|
236
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
246
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsTrigger, decorators: [{
|
|
237
247
|
type: Directive,
|
|
238
248
|
args: [{
|
|
239
249
|
selector: '[hlmTabsTrigger]',
|
|
@@ -256,8 +266,8 @@ const HlmTabsImports = [
|
|
|
256
266
|
HlmTabsPaginatedList,
|
|
257
267
|
];
|
|
258
268
|
class HlmTabsModule {
|
|
259
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
260
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.
|
|
269
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
270
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsModule, imports: [HlmTabs,
|
|
261
271
|
HlmTabsList,
|
|
262
272
|
HlmTabsTrigger,
|
|
263
273
|
HlmTabsContent,
|
|
@@ -268,9 +278,9 @@ class HlmTabsModule {
|
|
|
268
278
|
HlmTabsContent,
|
|
269
279
|
HlmTabsContentLazy,
|
|
270
280
|
HlmTabsPaginatedList] });
|
|
271
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.
|
|
281
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsModule, imports: [HlmTabsPaginatedList] });
|
|
272
282
|
}
|
|
273
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
283
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTabsModule, decorators: [{
|
|
274
284
|
type: NgModule,
|
|
275
285
|
args: [{
|
|
276
286
|
imports: [...HlmTabsImports],
|
|
@@ -283,4 +293,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
283
293
|
*/
|
|
284
294
|
|
|
285
295
|
export { HlmTabs, HlmTabsContent, HlmTabsContentLazy, HlmTabsImports, HlmTabsList, HlmTabsModule, HlmTabsPaginatedList, HlmTabsTrigger, listVariants };
|
|
286
|
-
|
|
296
|
+
|
package/textarea/README.md
CHANGED
|
@@ -1,11 +1,288 @@
|
|
|
1
|
-
# Textarea
|
|
1
|
+
# Textarea (`@egose/shadcn-theme-ng/textarea`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A multi-line text input, equivalent to [shadcn/ui Textarea](https://ui.shadcn.com/docs/components/textarea). This subpath ships a single thin styling directive, `HlmTextarea` (`[hlmTextarea]`), over spartan-ng's `BrnTextarea` primitive (plus `BrnFieldControlDescribedBy` for form-field hint/error wiring). All behavior — value binding, validation, auto-sizing — comes from the Brn primitive and Angular forms; this package only applies shadcn styling (border, focus ring, invalid state, placeholder color).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> **Ships as:** `@egose/shadcn-theme-ng/textarea` and `@egose/shadcn-theme-ng-tw/textarea` (the `tw:`-prefixed Tailwind variant). See the [package README](../../README.md) for install steps, peer dependencies, Tailwind setup, and testing/release guidance. Do not publish this project directory independently.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
10
|
+
# Plain Tailwind (no prefix)
|
|
11
|
+
npm install @egose/shadcn-theme-ng
|
|
12
|
+
|
|
13
|
+
# Or the tw:-prefixed variant
|
|
14
|
+
npm install @egose/shadcn-theme-ng-tw
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`@spartan-ng/brain` arrives transitively; `FormsModule`/`ReactiveFormsModule` come from your app when you need form bindings. See the [package README](../../README.md) for the full peer-dependency table.
|
|
18
|
+
|
|
19
|
+
## Imports
|
|
20
|
+
|
|
21
|
+
All public symbols are re-exported from `projects/textarea/src/public-api.ts`:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { HlmTextarea, HlmTextareaImports, HlmTextareaModule } from '@egose/shadcn-theme-ng/textarea';
|
|
25
|
+
// tw variant:
|
|
26
|
+
// import { HlmTextarea, HlmTextareaImports, HlmTextareaModule } from '@egose/shadcn-theme-ng-tw/textarea';
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Standalone-component usage (preferred):
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { Component } from '@angular/core';
|
|
33
|
+
import { HlmTextareaImports } from '@egose/shadcn-theme-ng/textarea';
|
|
34
|
+
|
|
35
|
+
@Component({
|
|
36
|
+
selector: 'app-demo',
|
|
37
|
+
standalone: true,
|
|
38
|
+
imports: [...HlmTextareaImports],
|
|
39
|
+
template: `<textarea hlmTextarea placeholder="Type here…"></textarea>`,
|
|
40
|
+
})
|
|
41
|
+
export class DemoComponent {}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
NgModule usage:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { NgModule } from '@angular/core';
|
|
48
|
+
import { HlmTextareaModule } from '@egose/shadcn-theme-ng/textarea';
|
|
49
|
+
|
|
50
|
+
@NgModule({ imports: [HlmTextareaModule] })
|
|
51
|
+
export class FeatureModule {}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| Symbol | Kind | Description |
|
|
55
|
+
| -------------------- | ------------- | ---------------------------------------------------- |
|
|
56
|
+
| `HlmTextarea` | Directive | `[hlmTextarea]` — shadcn styling over `BrnTextarea`. |
|
|
57
|
+
| `HlmTextareaImports` | `const` array | `[HlmTextarea]` — spread into `imports: [...]`. |
|
|
58
|
+
| `HlmTextareaModule` | NgModule | Imports + re-exports `HlmTextarea`. |
|
|
59
|
+
|
|
60
|
+
## Anatomy / Structure
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<!-- basic -->
|
|
64
|
+
<textarea hlmTextarea placeholder="Tell us about yourself…"></textarea>
|
|
65
|
+
|
|
66
|
+
<!-- with label + hint -->
|
|
67
|
+
<div class="space-y-2">
|
|
68
|
+
<label hlmLabel for="bio">Bio</label>
|
|
69
|
+
<textarea hlmTextarea id="bio" rows="4" placeholder="Short bio…"></textarea>
|
|
70
|
+
<p class="text-sm text-muted-foreground">Up to 500 characters.</p>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<!-- reactive form -->
|
|
74
|
+
<textarea hlmTextarea formControlName="notes" rows="5"></textarea>
|
|
75
|
+
|
|
76
|
+
<!-- forced invalid state -->
|
|
77
|
+
<textarea hlmTextarea [forceInvalid]="true"></textarea>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API reference
|
|
81
|
+
|
|
82
|
+
### `HlmTextarea` — selector `[hlmTextarea]` (directive, hosts `BrnTextarea` + `BrnFieldControlDescribedBy`)
|
|
83
|
+
|
|
84
|
+
The directive declares **no own inputs/outputs**. All behavior comes from host directives:
|
|
85
|
+
|
|
86
|
+
| Input | Source | Description |
|
|
87
|
+
| -------------- | ---------------------------- | ---------------------------------------------------------------------------------------- |
|
|
88
|
+
| `id` | `BrnTextarea` | Element id (pairs with `<label for>` and form-field wiring). |
|
|
89
|
+
| `forceInvalid` | `BrnTextarea` | Force the `data-[matches-spartan-invalid=true]` invalid styles even without form errors. |
|
|
90
|
+
| (described-by) | `BrnFieldControlDescribedBy` | Auto-wires `aria-describedby` to enclosing form-field hint/error. |
|
|
91
|
+
|
|
92
|
+
Standard native attributes (`rows`, `placeholder`, `disabled`, `readonly`, `maxlength`, `name`, …) and Angular form bindings (`formControl`, `formControlName`, `ngModel`) work as usual through the underlying `<textarea>`.
|
|
93
|
+
|
|
94
|
+
Host: `data-slot="textarea"`. Invalid styling keys off `data-[matches-spartan-invalid=true]` (`border-destructive`, `ring-destructive`). Disabled state renders `cursor-not-allowed` + `opacity-50`. User `class` is preserved and merged via `classes()`.
|
|
95
|
+
|
|
96
|
+
## Examples
|
|
97
|
+
|
|
98
|
+
### 1. Basic usage with label
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
// demo-basic.component.ts
|
|
102
|
+
import { Component } from '@angular/core';
|
|
103
|
+
import { HlmTextareaImports } from '@egose/shadcn-theme-ng/textarea';
|
|
104
|
+
import { HlmLabel } from '@egose/shadcn-theme-ng/label';
|
|
105
|
+
|
|
106
|
+
@Component({
|
|
107
|
+
selector: 'demo-basic',
|
|
108
|
+
standalone: true,
|
|
109
|
+
imports: [...HlmTextareaImports, HlmLabel],
|
|
110
|
+
template: `
|
|
111
|
+
<div class="space-y-2">
|
|
112
|
+
<label hlmLabel for="bio">Bio</label>
|
|
113
|
+
<textarea hlmTextarea id="bio" rows="4" placeholder="Tell us about yourself…"></textarea>
|
|
114
|
+
</div>
|
|
115
|
+
`,
|
|
116
|
+
})
|
|
117
|
+
export class DemoBasic {}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 2. Reactive form with validation + character count
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// demo-reactive.component.ts
|
|
124
|
+
import { Component } from '@angular/core';
|
|
125
|
+
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
126
|
+
import { HlmTextareaImports } from '@egose/shadcn-theme-ng/textarea';
|
|
127
|
+
import { HlmLabel } from '@egose/shadcn-theme-ng/label';
|
|
128
|
+
|
|
129
|
+
@Component({
|
|
130
|
+
selector: 'demo-reactive',
|
|
131
|
+
standalone: true,
|
|
132
|
+
imports: [...HlmTextareaImports, ReactiveFormsModule, HlmLabel],
|
|
133
|
+
template: `
|
|
134
|
+
<form [formGroup]="form" class="space-y-2">
|
|
135
|
+
<label hlmLabel for="feedback">Feedback</label>
|
|
136
|
+
<textarea
|
|
137
|
+
hlmTextarea
|
|
138
|
+
id="feedback"
|
|
139
|
+
rows="5"
|
|
140
|
+
maxlength="500"
|
|
141
|
+
placeholder="What did you think?"
|
|
142
|
+
formControlName="feedback"
|
|
143
|
+
></textarea>
|
|
144
|
+
<div class="flex justify-between text-sm">
|
|
145
|
+
<span class="text-destructive">
|
|
146
|
+
@if (form.controls.feedback.hasError('required') && form.controls.feedback.touched) {
|
|
147
|
+
Feedback is required.
|
|
148
|
+
} @else if (form.controls.feedback.hasError('minlength')) {
|
|
149
|
+
At least 10 characters.
|
|
150
|
+
}
|
|
151
|
+
</span>
|
|
152
|
+
<span class="text-muted-foreground">{{ form.controls.feedback.value?.length ?? 0 }}/500</span>
|
|
153
|
+
</div>
|
|
154
|
+
</form>
|
|
155
|
+
`,
|
|
156
|
+
})
|
|
157
|
+
export class DemoReactive {
|
|
158
|
+
readonly form = new FormGroup({
|
|
159
|
+
feedback: new FormControl('', [Validators.required, Validators.minLength(10)]),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 3. Template-driven form (`ngModel`)
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
// demo-template.component.ts
|
|
168
|
+
import { Component } from '@angular/core';
|
|
169
|
+
import { FormsModule } from '@angular/forms';
|
|
170
|
+
import { HlmTextareaImports } from '@egose/shadcn-theme-ng/textarea';
|
|
171
|
+
import { HlmLabel } from '@egose/shadcn-theme-ng/label';
|
|
172
|
+
|
|
173
|
+
@Component({
|
|
174
|
+
selector: 'demo-template',
|
|
175
|
+
standalone: true,
|
|
176
|
+
imports: [...HlmTextareaImports, FormsModule, HlmLabel],
|
|
177
|
+
template: `
|
|
178
|
+
<div class="space-y-2">
|
|
179
|
+
<label hlmLabel for="notes">Notes</label>
|
|
180
|
+
<textarea hlmTextarea id="notes" name="notes" rows="3" [(ngModel)]="notes"></textarea>
|
|
181
|
+
<p class="text-sm text-muted-foreground">Preview: {{ notes || '—' }}</p>
|
|
182
|
+
</div>
|
|
183
|
+
`,
|
|
184
|
+
})
|
|
185
|
+
export class DemoTemplate {
|
|
186
|
+
notes = '';
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 4. Disabled / readonly / error states
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
// demo-states.component.ts
|
|
194
|
+
import { Component } from '@angular/core';
|
|
195
|
+
import { HlmTextareaImports } from '@egose/shadcn-theme-ng/textarea';
|
|
196
|
+
import { HlmLabel } from '@egose/shadcn-theme-ng/label';
|
|
197
|
+
|
|
198
|
+
@Component({
|
|
199
|
+
selector: 'demo-states',
|
|
200
|
+
standalone: true,
|
|
201
|
+
imports: [...HlmTextareaImports, HlmLabel],
|
|
202
|
+
template: `
|
|
203
|
+
<div class="space-y-4">
|
|
204
|
+
<div class="space-y-2">
|
|
205
|
+
<label hlmLabel for="t-disabled">Disabled</label>
|
|
206
|
+
<textarea hlmTextarea id="t-disabled" disabled placeholder="Cannot edit…"></textarea>
|
|
207
|
+
</div>
|
|
208
|
+
<div class="space-y-2">
|
|
209
|
+
<label hlmLabel for="t-readonly">Readonly</label>
|
|
210
|
+
<textarea hlmTextarea id="t-readonly" readonly rows="2">Submitted value, read only.</textarea>
|
|
211
|
+
</div>
|
|
212
|
+
<div class="space-y-2">
|
|
213
|
+
<label hlmLabel for="t-invalid">Forced invalid</label>
|
|
214
|
+
<textarea hlmTextarea id="t-invalid" [forceInvalid]="true" rows="2">Fails custom rule.</textarea>
|
|
215
|
+
<p class="text-sm text-destructive">Custom server error goes here.</p>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
`,
|
|
219
|
+
})
|
|
220
|
+
export class DemoStates {}
|
|
11
221
|
```
|
|
222
|
+
|
|
223
|
+
### 5. Inside a form-field (hint + error wiring)
|
|
224
|
+
|
|
225
|
+
`BrnFieldControlDescribedBy` auto-links the textarea to the surrounding field's hint/error for screen readers:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
// demo-field.component.ts
|
|
229
|
+
import { Component } from '@angular/core';
|
|
230
|
+
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
231
|
+
import { HlmTextareaImports } from '@egose/shadcn-theme-ng/textarea';
|
|
232
|
+
import { HlmFormFieldImports } from '@egose/shadcn-theme-ng/form-field';
|
|
233
|
+
|
|
234
|
+
@Component({
|
|
235
|
+
selector: 'demo-field',
|
|
236
|
+
standalone: true,
|
|
237
|
+
imports: [...HlmTextareaImports, ...HlmFormFieldImports, ReactiveFormsModule],
|
|
238
|
+
template: `
|
|
239
|
+
<form [formGroup]="form">
|
|
240
|
+
<hlm-form-field>
|
|
241
|
+
<label hlmLabel for="desc">Description</label>
|
|
242
|
+
<textarea hlmTextarea id="desc" formControlName="description" rows="4"></textarea>
|
|
243
|
+
<hlm-hint>Describe the issue in a few sentences.</hlm-hint>
|
|
244
|
+
<hlm-error>Description is required.</hlm-error>
|
|
245
|
+
</hlm-form-field>
|
|
246
|
+
</form>
|
|
247
|
+
`,
|
|
248
|
+
})
|
|
249
|
+
export class DemoField {
|
|
250
|
+
readonly form = new FormGroup({ description: new FormControl('', Validators.required) });
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
(Exact `hlm-form-field`/`hlm-hint`/`hlm-error` selector names come from `@egose/shadcn-theme-ng/form-field` — check that subpath for the current API.)
|
|
255
|
+
|
|
256
|
+
### 6. Autosize / custom sizing
|
|
257
|
+
|
|
258
|
+
The base styles include `field-sizing-content` + `min-h-16`, so the textarea grows with content in supporting browsers. Combine with `rows` and width utilities:
|
|
259
|
+
|
|
260
|
+
```html
|
|
261
|
+
<!-- fixed 8 rows, full width (default w-full) -->
|
|
262
|
+
<textarea hlmTextarea rows="8" placeholder="Long-form answer…"></textarea>
|
|
263
|
+
|
|
264
|
+
<!-- constrained width + no manual resize -->
|
|
265
|
+
<textarea hlmTextarea rows="4" class="max-w-xl resize-none" placeholder="No drag handle…"></textarea>
|
|
266
|
+
|
|
267
|
+
<!-- tall monospace variant for code -->
|
|
268
|
+
<textarea hlmTextarea rows="10" class="font-mono text-sm" spellcheck="false"></textarea>
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Accessibility notes
|
|
272
|
+
|
|
273
|
+
- Every textarea needs a visible `<label>` (matching `for`/`id`) — placeholders are not labels.
|
|
274
|
+
- Wire hint/error text with `aria-describedby` (automatic inside `hlm-form-field` via `BrnFieldControlDescribedBy`; manual `aria-describedby="hint-id"` otherwise).
|
|
275
|
+
- Surface validation errors both visually (`forceInvalid` / form errors → `border-destructive`) and as text adjacent to the field; do not rely on color alone.
|
|
276
|
+
- Keep `maxlength` announcements truthful — show a live character count for constrained fields.
|
|
277
|
+
- Disabled textareas are skipped by assistive tech; use `readonly` when the value must remain perceivable but not editable.
|
|
278
|
+
|
|
279
|
+
## Theming / CSS variables
|
|
280
|
+
|
|
281
|
+
Keys off theme tokens (`border-input`, `bg-input/30` in dark mode, `ring-ring/50`, `text-muted-foreground` placeholder, `border-destructive`/`ring-destructive` invalid). Follows your shadcn theme automatically; extend via `class` (merged through `classes()`).
|
|
282
|
+
|
|
283
|
+
## Related subpaths
|
|
284
|
+
|
|
285
|
+
- `@egose/shadcn-theme-ng/input` — single-line sibling control.
|
|
286
|
+
- `@egose/shadcn-theme-ng/label` — accessible labels.
|
|
287
|
+
- `@egose/shadcn-theme-ng/form-field` / `@egose/shadcn-theme-ng/form-textarea` — labeled field with hint/error wiring.
|
|
288
|
+
- `@egose/shadcn-theme-ng/button` — submit actions for textarea forms.
|
|
@@ -8,12 +8,12 @@ import { classes } from '@egose/shadcn-theme-ng-tw/utils';
|
|
|
8
8
|
|
|
9
9
|
class HlmTextarea {
|
|
10
10
|
constructor() {
|
|
11
|
-
classes(() => 'border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 data-[matches-spartan-invalid=true]:ring-destructive/20 dark:data-[matches-spartan-invalid=true]:ring-destructive/40 data-[matches-spartan-invalid=true]:border-destructive dark:data-[matches-spartan-invalid=true]:border-destructive/50 rounded-md border bg-transparent px-2.5 py-2 text-base shadow-xs transition-[color,box-shadow] focus-visible:ring-3 data-[matches-spartan-invalid=true]:ring-3 md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 w-full outline-none disabled:cursor-not-allowed disabled:opacity-50');
|
|
11
|
+
classes(() => 'tw:border-input tw:dark:bg-input/30 tw:focus-visible:border-ring tw:focus-visible:ring-ring/50 tw:data-[matches-spartan-invalid=true]:ring-destructive/20 tw:dark:data-[matches-spartan-invalid=true]:ring-destructive/40 tw:data-[matches-spartan-invalid=true]:border-destructive tw:dark:data-[matches-spartan-invalid=true]:border-destructive/50 tw:rounded-md tw:border tw:bg-transparent tw:px-2.5 tw:py-2 tw:text-base tw:shadow-xs tw:transition-[color,box-shadow] tw:focus-visible:ring-3 tw:data-[matches-spartan-invalid=true]:ring-3 tw:md:text-sm tw:placeholder:text-muted-foreground tw:flex tw:field-sizing-content tw:min-h-16 tw:w-full tw:outline-none tw:disabled:cursor-not-allowed tw:disabled:opacity-50');
|
|
12
12
|
}
|
|
13
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
14
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.
|
|
13
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTextarea, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
14
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmTextarea, isStandalone: true, selector: "[hlmTextarea]", host: { attributes: { "data-slot": "textarea" } }, hostDirectives: [{ directive: i1.BrnTextarea, inputs: ["id", "id", "forceInvalid", "forceInvalid"] }, { directive: i2.BrnFieldControlDescribedBy }], ngImport: i0 });
|
|
15
15
|
}
|
|
16
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
16
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTextarea, decorators: [{
|
|
17
17
|
type: Directive,
|
|
18
18
|
args: [{
|
|
19
19
|
selector: '[hlmTextarea]',
|
|
@@ -27,11 +27,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
27
27
|
*/
|
|
28
28
|
const HlmTextareaImports = [HlmTextarea];
|
|
29
29
|
class HlmTextareaModule {
|
|
30
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.
|
|
31
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.
|
|
32
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.
|
|
30
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTextareaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
31
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: HlmTextareaModule, imports: [HlmTextarea], exports: [HlmTextarea] });
|
|
32
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTextareaModule });
|
|
33
33
|
}
|
|
34
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.
|
|
34
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmTextareaModule, decorators: [{
|
|
35
35
|
type: NgModule,
|
|
36
36
|
args: [{
|
|
37
37
|
imports: [...HlmTextareaImports],
|
|
@@ -44,4 +44,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
|
|
|
44
44
|
*/
|
|
45
45
|
|
|
46
46
|
export { HlmTextarea, HlmTextareaImports, HlmTextareaModule };
|
|
47
|
-
|
|
47
|
+
|