@lifecorner/angular-ui-kit 3.8.0 → 3.9.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/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs +39 -6
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/_horizon.scss +46 -12
- package/src/styles/horizon.shell.spec.ts +67 -0
- package/src/styles/horizon.spec.ts +6 -4
- package/types/lifecorner-angular-ui-kit-app-shell.d.ts +15 -4
- package/types/lifecorner-angular-ui-kit-button.d.ts +30 -0
- package/types/lifecorner-angular-ui-kit-page-header.d.ts +6 -1
- package/types/lifecorner-angular-ui-kit-skeleton.d.ts +7 -1
|
@@ -29,8 +29,8 @@ var AppShellComponent = class AppShellComponent {
|
|
|
29
29
|
transformFunction: null
|
|
30
30
|
} },
|
|
31
31
|
ngImport: i0,
|
|
32
|
-
template: "<div [class]=\"shellClasses()\">\n <div class=\"lc-app-shell__header\"><ng-content select=\"[shell-header]\" /></div>\n <div class=\"lc-app-shell__nav\"><ng-content select=\"[shell-nav]\" /></div>\n <div class=\"lc-app-shell__body\"><ng-content /></div>\n @if (horizon()) {\n <div class=\"lc-app-shell__horizon lc-horizon\"
|
|
33
|
-
styles: [":host{display:block}.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 240px);--_clearance: var(--lc-app-shell-bottom-clearance, calc(112px + env(safe-area-inset-bottom, 0px)) );display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto 1fr;grid-template-areas:\"header\" \"body\" \"end\";min-height:100vh;min-height:100dvh;box-sizing:border-box;background-color:var(--lc-app-shell-bg, var(--color-background));background-image:var(--lc-app-shell-bg-image, var(--app-background-image, none))}.lc-app-shell__header{grid-area:header;min-width:0;padding-top:env(safe-area-inset-top,0px);padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__body{grid-area:body;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__nav{display:none}.lc-app-shell__horizon{grid-area:end;min-width:0}.lc-app-shell__footer{grid-area:end;align-self:end;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell--horizon .lc-app-shell__footer{position:relative;z-index:1}.lc-app-shell__footer:empty,.lc-app-shell__header:empty{display:none}.lc-app-shell__bottom-nav{display:contents}@media(max-width:1023.98px){.lc-app-shell:not(.lc-app-shell--horizon):has(>.lc-app-shell__bottom-nav:not(:empty)){padding-bottom:var(--_clearance)}}@media(min-width:1024px){.lc-app-shell{grid-template-columns:var(--_nav-width) minmax(0,1fr);grid-template-areas:\"header header\" \"nav body\" \"end end\"}.lc-app-shell:has(>.lc-app-shell__nav:empty){grid-template-columns:minmax(0,1fr);grid-template-areas:\"header\" \"body\" \"end\"}.lc-app-shell__nav{grid-area:nav;display:block;min-width:0;position:sticky;top:0;align-self:start;max-height:100vh;max-height:100dvh;overflow-y:auto;padding-left:env(safe-area-inset-left,0px)}.lc-app-shell__nav:empty{display:none}.lc-app-shell:not(:has(>.lc-app-shell__nav:empty)) .lc-app-shell__body{padding-left:0}.lc-app-shell__bottom-nav{display:none}}@media(min-width:1280px){.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 360px);--_hairline: var(--color-hairline, var(--color-border));background:linear-gradient(var(--_hairline),var(--_hairline)) right calc(var(--_aside-width) - 1px) top/1px 100% no-repeat,linear-gradient(var(--color-background-low),var(--color-background-low)) right top/var(--_aside-width) 100% no-repeat}}@media(min-width:1440px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 248px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 400px)}}@media(min-width:1920px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 280px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 460px)}}@media(forced-colors:active){.lc-app-shell__header{background:none}}\n"],
|
|
32
|
+
template: "<div [class]=\"shellClasses()\">\n <div class=\"lc-app-shell__header\"><ng-content select=\"[shell-header]\" /></div>\n <div class=\"lc-app-shell__nav\"><ng-content select=\"[shell-nav]\" /></div>\n <div class=\"lc-app-shell__body\"><ng-content /></div>\n @if (horizon()) {\n <div class=\"lc-app-shell__horizon lc-horizon\" aria-hidden=\"true\"><ng-content select=\"[shell-horizon-figure]\" /></div>\n }\n <div class=\"lc-app-shell__footer\"><ng-content select=\"[shell-footer]\" /></div>\n <div class=\"lc-app-shell__bottom-nav\"><ng-content select=\"[shell-bottom-nav]\" /></div>\n</div>\n",
|
|
33
|
+
styles: [":host{display:block}.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 240px);--_clearance: var(--lc-app-shell-bottom-clearance, calc(112px + env(safe-area-inset-bottom, 0px)) );display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto 1fr;grid-template-areas:\"header\" \"body\" \"end\";min-height:100vh;min-height:100dvh;box-sizing:border-box;background-color:var(--lc-app-shell-bg, var(--color-background));background-image:var(--lc-app-shell-bg-image, var(--app-background-image, none))}.lc-app-shell__header{grid-area:header;min-width:0;padding-top:env(safe-area-inset-top,0px);padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__body{grid-area:body;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__nav{display:none}.lc-app-shell__horizon{grid-area:end;min-width:0}.lc-app-shell__footer{grid-area:end;align-self:end;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell--horizon{grid-template-rows:auto auto 1fr auto}.lc-app-shell--horizon .lc-app-shell__footer{position:relative;z-index:1;grid-row:4;grid-column:1/-1;background-color:var(--color-land-3)}.lc-app-shell__footer:empty,.lc-app-shell__header:empty{display:none}.lc-app-shell__bottom-nav{display:contents}@media(max-width:1023.98px){.lc-app-shell:not(.lc-app-shell--horizon):has(>.lc-app-shell__bottom-nav:not(:empty)){padding-bottom:var(--_clearance)}}@media(min-width:1024px){.lc-app-shell{grid-template-columns:var(--_nav-width) minmax(0,1fr);grid-template-areas:\"header header\" \"nav body\" \"end end\"}.lc-app-shell:has(>.lc-app-shell__nav:empty){grid-template-columns:minmax(0,1fr);grid-template-areas:\"header\" \"body\" \"end\"}.lc-app-shell__nav{grid-area:nav;display:block;min-width:0;position:sticky;top:0;align-self:start;max-height:100vh;max-height:100dvh;overflow-y:auto;padding-left:env(safe-area-inset-left,0px)}.lc-app-shell__nav:empty{display:none}.lc-app-shell:not(:has(>.lc-app-shell__nav:empty)) .lc-app-shell__body{padding-left:0}.lc-app-shell__bottom-nav{display:none}}@media(min-width:1280px){.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 360px);--_hairline: var(--color-hairline, var(--color-border));background:linear-gradient(var(--_hairline),var(--_hairline)) right calc(var(--_aside-width) - 1px) top/1px 100% no-repeat,linear-gradient(var(--color-background-low),var(--color-background-low)) right top/var(--_aside-width) 100% no-repeat}}@media(min-width:1440px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 248px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 400px)}}@media(min-width:1920px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 280px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 460px)}}@media(forced-colors:active){.lc-app-shell__header{background:none}}\n"],
|
|
34
34
|
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
35
35
|
});
|
|
36
36
|
};
|
|
@@ -45,8 +45,8 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
45
45
|
selector: "lc-app-shell",
|
|
46
46
|
standalone: true,
|
|
47
47
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
48
|
-
template: "<div [class]=\"shellClasses()\">\n <div class=\"lc-app-shell__header\"><ng-content select=\"[shell-header]\" /></div>\n <div class=\"lc-app-shell__nav\"><ng-content select=\"[shell-nav]\" /></div>\n <div class=\"lc-app-shell__body\"><ng-content /></div>\n @if (horizon()) {\n <div class=\"lc-app-shell__horizon lc-horizon\"
|
|
49
|
-
styles: [":host{display:block}.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 240px);--_clearance: var(--lc-app-shell-bottom-clearance, calc(112px + env(safe-area-inset-bottom, 0px)) );display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto 1fr;grid-template-areas:\"header\" \"body\" \"end\";min-height:100vh;min-height:100dvh;box-sizing:border-box;background-color:var(--lc-app-shell-bg, var(--color-background));background-image:var(--lc-app-shell-bg-image, var(--app-background-image, none))}.lc-app-shell__header{grid-area:header;min-width:0;padding-top:env(safe-area-inset-top,0px);padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__body{grid-area:body;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__nav{display:none}.lc-app-shell__horizon{grid-area:end;min-width:0}.lc-app-shell__footer{grid-area:end;align-self:end;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell--horizon .lc-app-shell__footer{position:relative;z-index:1}.lc-app-shell__footer:empty,.lc-app-shell__header:empty{display:none}.lc-app-shell__bottom-nav{display:contents}@media(max-width:1023.98px){.lc-app-shell:not(.lc-app-shell--horizon):has(>.lc-app-shell__bottom-nav:not(:empty)){padding-bottom:var(--_clearance)}}@media(min-width:1024px){.lc-app-shell{grid-template-columns:var(--_nav-width) minmax(0,1fr);grid-template-areas:\"header header\" \"nav body\" \"end end\"}.lc-app-shell:has(>.lc-app-shell__nav:empty){grid-template-columns:minmax(0,1fr);grid-template-areas:\"header\" \"body\" \"end\"}.lc-app-shell__nav{grid-area:nav;display:block;min-width:0;position:sticky;top:0;align-self:start;max-height:100vh;max-height:100dvh;overflow-y:auto;padding-left:env(safe-area-inset-left,0px)}.lc-app-shell__nav:empty{display:none}.lc-app-shell:not(:has(>.lc-app-shell__nav:empty)) .lc-app-shell__body{padding-left:0}.lc-app-shell__bottom-nav{display:none}}@media(min-width:1280px){.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 360px);--_hairline: var(--color-hairline, var(--color-border));background:linear-gradient(var(--_hairline),var(--_hairline)) right calc(var(--_aside-width) - 1px) top/1px 100% no-repeat,linear-gradient(var(--color-background-low),var(--color-background-low)) right top/var(--_aside-width) 100% no-repeat}}@media(min-width:1440px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 248px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 400px)}}@media(min-width:1920px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 280px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 460px)}}@media(forced-colors:active){.lc-app-shell__header{background:none}}\n"]
|
|
48
|
+
template: "<div [class]=\"shellClasses()\">\n <div class=\"lc-app-shell__header\"><ng-content select=\"[shell-header]\" /></div>\n <div class=\"lc-app-shell__nav\"><ng-content select=\"[shell-nav]\" /></div>\n <div class=\"lc-app-shell__body\"><ng-content /></div>\n @if (horizon()) {\n <div class=\"lc-app-shell__horizon lc-horizon\" aria-hidden=\"true\"><ng-content select=\"[shell-horizon-figure]\" /></div>\n }\n <div class=\"lc-app-shell__footer\"><ng-content select=\"[shell-footer]\" /></div>\n <div class=\"lc-app-shell__bottom-nav\"><ng-content select=\"[shell-bottom-nav]\" /></div>\n</div>\n",
|
|
49
|
+
styles: [":host{display:block}.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 240px);--_clearance: var(--lc-app-shell-bottom-clearance, calc(112px + env(safe-area-inset-bottom, 0px)) );display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto 1fr;grid-template-areas:\"header\" \"body\" \"end\";min-height:100vh;min-height:100dvh;box-sizing:border-box;background-color:var(--lc-app-shell-bg, var(--color-background));background-image:var(--lc-app-shell-bg-image, var(--app-background-image, none))}.lc-app-shell__header{grid-area:header;min-width:0;padding-top:env(safe-area-inset-top,0px);padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__body{grid-area:body;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell__nav{display:none}.lc-app-shell__horizon{grid-area:end;min-width:0}.lc-app-shell__footer{grid-area:end;align-self:end;min-width:0;padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px)}.lc-app-shell--horizon{grid-template-rows:auto auto 1fr auto}.lc-app-shell--horizon .lc-app-shell__footer{position:relative;z-index:1;grid-row:4;grid-column:1/-1;background-color:var(--color-land-3)}.lc-app-shell__footer:empty,.lc-app-shell__header:empty{display:none}.lc-app-shell__bottom-nav{display:contents}@media(max-width:1023.98px){.lc-app-shell:not(.lc-app-shell--horizon):has(>.lc-app-shell__bottom-nav:not(:empty)){padding-bottom:var(--_clearance)}}@media(min-width:1024px){.lc-app-shell{grid-template-columns:var(--_nav-width) minmax(0,1fr);grid-template-areas:\"header header\" \"nav body\" \"end end\"}.lc-app-shell:has(>.lc-app-shell__nav:empty){grid-template-columns:minmax(0,1fr);grid-template-areas:\"header\" \"body\" \"end\"}.lc-app-shell__nav{grid-area:nav;display:block;min-width:0;position:sticky;top:0;align-self:start;max-height:100vh;max-height:100dvh;overflow-y:auto;padding-left:env(safe-area-inset-left,0px)}.lc-app-shell__nav:empty{display:none}.lc-app-shell:not(:has(>.lc-app-shell__nav:empty)) .lc-app-shell__body{padding-left:0}.lc-app-shell__bottom-nav{display:none}}@media(min-width:1280px){.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 360px);--_hairline: var(--color-hairline, var(--color-border));background:linear-gradient(var(--_hairline),var(--_hairline)) right calc(var(--_aside-width) - 1px) top/1px 100% no-repeat,linear-gradient(var(--color-background-low),var(--color-background-low)) right top/var(--_aside-width) 100% no-repeat}}@media(min-width:1440px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 248px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 400px)}}@media(min-width:1920px){.lc-app-shell{--_nav-width: var(--lc-app-shell-nav-width, 280px)}.lc-app-shell:has(.lc-app-page__aside)>.lc-app-shell__header{--_aside-width: var(--lc-app-page-aside-width, 460px)}}@media(forced-colors:active){.lc-app-shell__header{background:none}}\n"]
|
|
50
50
|
}]
|
|
51
51
|
}],
|
|
52
52
|
propDecorators: { horizon: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-app-shell.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/app-shell/app-shell.component.ts","../../../../libs/angular-ui-kit/src/lib/app-shell/app-shell.component.html","../../../../libs/angular-ui-kit/src/lib/app-shell/app-page.component.ts","../../../../libs/angular-ui-kit/src/lib/app-shell/app-page.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\n\n/**\n * App shell: the frame around every page of an app — header, side navigation,\n * page, bottom navigation bar, footer and the horizon — laid out for phones\n * first, with the DOCUMENT scrolling (not an inner container), so the iOS\n * status-bar tap, address-bar collapse and pull-to-refresh keep working.\n *\n * Slots (content projection by attribute):\n * - `[shell-header]` — the `lc-header`; scrolls away with the page. Gets the\n * top, left and right safe-area insets.\n * - `[shell-nav]` — the docked side navigation (`lc-sidenav mode=\"docked\"\n * [isOpen]=\"true\" width=\"100%\" [mobileBreakpoint]=\"0\"`), shown from\n * 1024 px in a column of 240 px (248 from 1440, 280 from 1920; override\n * with `--lc-app-shell-nav-width`) and sticky once the header has gone.\n * An empty slot takes no column.\n * - default — the page, usually an `lc-app-page` (or a `<router-outlet>`\n * whose pages use one). It spans to the window's right edge, so a page's\n * right column docks there.\n * - `[shell-bottom-nav]` — the `lc-bottom-nav`, shown below 1024 px. The shell\n * reserves its height at the end of the page (16 + 72 + 24 px plus the\n * safe-area inset; `--lc-app-shell-bottom-clearance`), so it never covers\n * content. With the horizon, the bar rests on the land instead.\n * - `[shell-footer]` — e.g. a compact `lc-footer`; on the horizon's land when\n * `horizon` is on, else after the page.\n *\n * `horizon` closes the page with the \"Weite\" horizon (`.lc-horizon` from the\n * kit's styles): full-bleed, below the side navigation and the page, filling\n * the rest of the screen — on Today, the sign-in pages and the shell pages.\n *\n * Needs `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1,\n * viewport-fit=cover\">` for the safe-area insets. Breakpoints are fixed\n * (1024 px side navigation, 1440 / 1920 px widths), so the layout works\n * before JavaScript runs (SSR, prerendering).\n *\n * @example\n * ```html\n * <lc-app-shell [horizon]=\"isToday()\">\n * <lc-header shell-header variant=\"transparent\" [sticky]=\"false\" … />\n * <lc-sidenav shell-nav mode=\"docked\" [isOpen]=\"true\" width=\"100%\" [mobileBreakpoint]=\"0\"\n * variant=\"transparent\" [items]=\"nav\" [activeRoute]=\"url()\" />\n * <router-outlet />\n * <lc-bottom-nav shell-bottom-nav variant=\"floating\" [items]=\"nav\" [activeRoute]=\"url()\" />\n * </lc-app-shell>\n * ```\n */\n@Component({\n selector: 'lc-app-shell',\n standalone: true,\n templateUrl: './app-shell.component.html',\n styleUrl: './app-shell.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AppShellComponent {\n /**\n * Close the page with the horizon (`.lc-horizon`): full width, below the\n * side navigation and the page, filling the rest of the screen; the footer\n * and the floating bar rest on its land.\n */\n readonly horizon = input(false);\n\n protected readonly shellClasses = computed(() => {\n const classes = ['lc-app-shell'];\n if (this.horizon()) classes.push('lc-app-shell--horizon');\n return classes.join(' ');\n });\n}\n","<div [class]=\"shellClasses()\">\n <div class=\"lc-app-shell__header\"><ng-content select=\"[shell-header]\" /></div>\n <div class=\"lc-app-shell__nav\"><ng-content select=\"[shell-nav]\" /></div>\n <div class=\"lc-app-shell__body\"><ng-content /></div>\n @if (horizon()) {\n <div class=\"lc-app-shell__horizon lc-horizon\"></div>\n }\n <div class=\"lc-app-shell__footer\"><ng-content select=\"[shell-footer]\" /></div>\n <div class=\"lc-app-shell__bottom-nav\"><ng-content select=\"[shell-bottom-nav]\" /></div>\n</div>\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\n\n/**\n * A page inside `lc-app-shell`: the `<main>` landmark with the page's content\n * centred at a reading width, and an optional right column docked to the\n * window's right edge (LK-6).\n *\n * - `<main [id]=\"mainId\">` holds the default slot as a column (24 px apart,\n * 40 px from 1024 px), centred and capped at `contentMaxWidth` (880 px of\n * content). Side padding 24 · 32 · 48 · 56 · 72 · 96 px at 360 · 640 ·\n * 1024 · 1280 · 1440 · 1920 px.\n * - `[page-aside]` is the right column: an `<aside>` AFTER `<main>` in the DOM,\n * shown from 1280 px at 360 px (400 from 1440, 460 from 1920; override\n * with `--lc-app-page-aside-width`), with a tint and a hairline that fade\n * downwards; inside `lc-app-shell` they start at the top of the window,\n * behind a transparent header. Below 1280 px it is hidden: show the page's narrow equivalent\n * inside main instead (e.g. a member row). It renders only with an\n * accessible name — `asideLabelledby` (the id of its heading) or\n * `asideAriaLabel`.\n * - `busy` marks the page as loading: `aria-busy=\"true\"` on `<main>` while a\n * skeleton stands in for the content (AS-12). No visual change.\n *\n * @example\n * ```html\n * <lc-app-page asideLabelledby=\"members-title\">\n * <lc-page-header … />\n * <lc-next-step-card … />\n * <section page-aside>\n * <h2 id=\"members-title\">Mitglieder</h2>\n * <lc-list [items]=\"members\" />\n * </section>\n * </lc-app-page>\n * ```\n */\n@Component({\n selector: 'lc-app-page',\n standalone: true,\n templateUrl: './app-page.component.html',\n styleUrl: './app-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AppPageComponent {\n /** Id of the `<main>` element (the skip link's target). */\n readonly mainId = input('main');\n\n /**\n * Widest the page content gets (CSS length; `none` for no cap). The default\n * keeps lines readable on wide screens: the page gains air, not line length.\n */\n readonly contentMaxWidth = input('880px');\n\n /** Id of the heading that names the right column (`aria-labelledby`). */\n readonly asideLabelledby = input('');\n\n /** Accessible name of the right column when it has no visible heading. */\n readonly asideAriaLabel = input('');\n\n /**\n * Marks the page as loading: `aria-busy=\"true\"` on its `<main>` while\n * `true`, no attribute while `false`. Set it while a skeleton stands in for\n * the content. Screen readers may hold back changes inside a busy region\n * until it clears, so a loading message that must be heard belongs outside\n * `<main>` (for example a `.sr-only` `role=\"status\"` next to the page) or is\n * static text. No visual change.\n * @default false\n */\n readonly busy = input(false);\n\n /** The right column renders only when it has an accessible name. */\n protected readonly hasAside = computed(() => !!(this.asideLabelledby() || this.asideAriaLabel()));\n\n protected readonly pageClasses = computed(() => {\n const classes = ['lc-app-page'];\n if (this.hasAside()) classes.push('lc-app-page--aside');\n return classes.join(' ');\n });\n}\n","<div [class]=\"pageClasses()\" [style.--lc-app-page-content-max]=\"contentMaxWidth()\">\n <main class=\"lc-app-page__main\" [id]=\"mainId()\" [attr.aria-busy]=\"busy() ? 'true' : null\">\n <div class=\"lc-app-page__content\"><ng-content /></div>\n </main>\n @if (hasAside()) {\n <aside\n class=\"lc-app-page__aside\"\n [attr.aria-labelledby]=\"asideLabelledby() || null\"\n [attr.aria-label]=\"asideLabelledby() ? null : asideAriaLabel()\"\n >\n <ng-content select=\"[page-aside]\" />\n </aside>\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-app-shell.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/app-shell/app-shell.component.ts","../../../../libs/angular-ui-kit/src/lib/app-shell/app-shell.component.html","../../../../libs/angular-ui-kit/src/lib/app-shell/app-page.component.ts","../../../../libs/angular-ui-kit/src/lib/app-shell/app-page.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\n\n/**\n * App shell: the frame around every page of an app — header, side navigation,\n * page, bottom navigation bar, footer and the horizon — laid out for phones\n * first, with the DOCUMENT scrolling (not an inner container), so the iOS\n * status-bar tap, address-bar collapse and pull-to-refresh keep working.\n *\n * Slots (content projection by attribute):\n * - `[shell-header]` — the `lc-header`; scrolls away with the page. Gets the\n * top, left and right safe-area insets.\n * - `[shell-nav]` — the docked side navigation (`lc-sidenav mode=\"docked\"\n * [isOpen]=\"true\" width=\"100%\" [mobileBreakpoint]=\"0\"`), shown from\n * 1024 px in a column of 240 px (248 from 1440, 280 from 1920; override\n * with `--lc-app-shell-nav-width`) and sticky once the header has gone.\n * An empty slot takes no column.\n * - default — the page, usually an `lc-app-page` (or a `<router-outlet>`\n * whose pages use one). It spans to the window's right edge, so a page's\n * right column docks there.\n * - `[shell-bottom-nav]` — the `lc-bottom-nav`, shown below 1024 px. The shell\n * reserves its height at the end of the page (16 + 72 + 24 px plus the\n * safe-area inset; `--lc-app-shell-bottom-clearance`), so it never covers\n * content. With the horizon, the bar rests on the land instead.\n * - `[shell-footer]` — e.g. a compact `lc-footer`; after the page, or with\n * `horizon` in a row of its own below the horizon, painted in the land's\n * colour (`--color-land-3`): the land grows by the footer's height, so\n * `--lc-horizon-land` stays the land above the footer and no page overrides\n * it (3.9, LK-12).\n * - `[shell-horizon-figure]` — Edu (or any decorative figure) on the horizon\n * line, left of the sun: `lc-character`, `<img>`, `<picture>` or an element\n * holding an inline `<svg>`. Projected as a direct child of `.lc-horizon`,\n * sized and placed by the horizon (`--lc-horizon-figure-size` / `-gap`).\n * Decorative: the horizon is `aria-hidden`, so give an `<img>` `alt=\"\"` and\n * nothing focusable. Shown only when `horizon` is on (3.9, AS-29).\n *\n * `horizon` closes the page with the \"Weite\" horizon (`.lc-horizon` from the\n * kit's styles): full-bleed, below the side navigation and the page, filling\n * the rest of the screen — on Today, the sign-in pages and the shell pages.\n *\n * Needs `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1,\n * viewport-fit=cover\">` for the safe-area insets. Breakpoints are fixed\n * (1024 px side navigation, 1440 / 1920 px widths), so the layout works\n * before JavaScript runs (SSR, prerendering).\n *\n * @example\n * ```html\n * <lc-app-shell [horizon]=\"isToday()\">\n * <lc-header shell-header variant=\"transparent\" [sticky]=\"false\" … />\n * <lc-sidenav shell-nav mode=\"docked\" [isOpen]=\"true\" width=\"100%\" [mobileBreakpoint]=\"0\"\n * variant=\"transparent\" [items]=\"nav\" [activeRoute]=\"url()\" />\n * <router-outlet />\n * <lc-bottom-nav shell-bottom-nav variant=\"floating\" [items]=\"nav\" [activeRoute]=\"url()\" />\n * </lc-app-shell>\n * ```\n */\n@Component({\n selector: 'lc-app-shell',\n standalone: true,\n templateUrl: './app-shell.component.html',\n styleUrl: './app-shell.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AppShellComponent {\n /**\n * Close the page with the horizon (`.lc-horizon`): full width, below the\n * side navigation and the page, filling the rest of the screen; the footer\n * (in a row of its own, which adds to the land) and the floating bar rest\n * on its land, and `[shell-horizon-figure]` stands on its line.\n * @default false\n */\n readonly horizon = input(false);\n\n protected readonly shellClasses = computed(() => {\n const classes = ['lc-app-shell'];\n if (this.horizon()) classes.push('lc-app-shell--horizon');\n return classes.join(' ');\n });\n}\n","<div [class]=\"shellClasses()\">\n <div class=\"lc-app-shell__header\"><ng-content select=\"[shell-header]\" /></div>\n <div class=\"lc-app-shell__nav\"><ng-content select=\"[shell-nav]\" /></div>\n <div class=\"lc-app-shell__body\"><ng-content /></div>\n @if (horizon()) {\n <div class=\"lc-app-shell__horizon lc-horizon\" aria-hidden=\"true\"><ng-content select=\"[shell-horizon-figure]\" /></div>\n }\n <div class=\"lc-app-shell__footer\"><ng-content select=\"[shell-footer]\" /></div>\n <div class=\"lc-app-shell__bottom-nav\"><ng-content select=\"[shell-bottom-nav]\" /></div>\n</div>\n","import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';\n\n/**\n * A page inside `lc-app-shell`: the `<main>` landmark with the page's content\n * centred at a reading width, and an optional right column docked to the\n * window's right edge (LK-6).\n *\n * - `<main [id]=\"mainId\">` holds the default slot as a column (24 px apart,\n * 40 px from 1024 px), centred and capped at `contentMaxWidth` (880 px of\n * content). Side padding 24 · 32 · 48 · 56 · 72 · 96 px at 360 · 640 ·\n * 1024 · 1280 · 1440 · 1920 px.\n * - `[page-aside]` is the right column: an `<aside>` AFTER `<main>` in the DOM,\n * shown from 1280 px at 360 px (400 from 1440, 460 from 1920; override\n * with `--lc-app-page-aside-width`), with a tint and a hairline that fade\n * downwards; inside `lc-app-shell` they start at the top of the window,\n * behind a transparent header. Below 1280 px it is hidden: show the page's narrow equivalent\n * inside main instead (e.g. a member row). It renders only with an\n * accessible name — `asideLabelledby` (the id of its heading) or\n * `asideAriaLabel`.\n * - `busy` marks the page as loading: `aria-busy=\"true\"` on `<main>` while a\n * skeleton stands in for the content (AS-12). No visual change.\n *\n * @example\n * ```html\n * <lc-app-page asideLabelledby=\"members-title\">\n * <lc-page-header … />\n * <lc-next-step-card … />\n * <section page-aside>\n * <h2 id=\"members-title\">Mitglieder</h2>\n * <lc-list [items]=\"members\" />\n * </section>\n * </lc-app-page>\n * ```\n */\n@Component({\n selector: 'lc-app-page',\n standalone: true,\n templateUrl: './app-page.component.html',\n styleUrl: './app-page.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AppPageComponent {\n /** Id of the `<main>` element (the skip link's target). */\n readonly mainId = input('main');\n\n /**\n * Widest the page content gets (CSS length; `none` for no cap). The default\n * keeps lines readable on wide screens: the page gains air, not line length.\n */\n readonly contentMaxWidth = input('880px');\n\n /** Id of the heading that names the right column (`aria-labelledby`). */\n readonly asideLabelledby = input('');\n\n /** Accessible name of the right column when it has no visible heading. */\n readonly asideAriaLabel = input('');\n\n /**\n * Marks the page as loading: `aria-busy=\"true\"` on its `<main>` while\n * `true`, no attribute while `false`. Set it while a skeleton stands in for\n * the content. Screen readers may hold back changes inside a busy region\n * until it clears, so a loading message that must be heard belongs outside\n * `<main>` (for example a `.sr-only` `role=\"status\"` next to the page) or is\n * static text. No visual change.\n * @default false\n */\n readonly busy = input(false);\n\n /** The right column renders only when it has an accessible name. */\n protected readonly hasAside = computed(() => !!(this.asideLabelledby() || this.asideAriaLabel()));\n\n protected readonly pageClasses = computed(() => {\n const classes = ['lc-app-page'];\n if (this.hasAside()) classes.push('lc-app-page--aside');\n return classes.join(' ');\n });\n}\n","<div [class]=\"pageClasses()\" [style.--lc-app-page-content-max]=\"contentMaxWidth()\">\n <main class=\"lc-app-page__main\" [id]=\"mainId()\" [attr.aria-busy]=\"busy() ? 'true' : null\">\n <div class=\"lc-app-page__content\"><ng-content /></div>\n </main>\n @if (hasAside()) {\n <aside\n class=\"lc-app-page__aside\"\n [attr.aria-labelledby]=\"asideLabelledby() || null\"\n [attr.aria-label]=\"asideLabelledby() ? null : asideAriaLabel()\"\n >\n <ng-content select=\"[page-aside]\" />\n </aside>\n }\n</div>\n"],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ var ButtonComponent = class ButtonComponent {
|
|
|
13
13
|
title = input("", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
|
|
14
14
|
disabledReason = input("", ...ngDevMode ? [{ debugName: "disabledReason" }] : /* istanbul ignore next */ []);
|
|
15
15
|
inline = input(false, ...ngDevMode ? [{ debugName: "inline" }] : /* istanbul ignore next */ []);
|
|
16
|
+
flush = input(false, ...ngDevMode ? [{ debugName: "flush" }] : /* istanbul ignore next */ []);
|
|
16
17
|
clicked = output();
|
|
17
18
|
focused = output();
|
|
18
19
|
blurred = output();
|
|
@@ -128,6 +129,13 @@ var ButtonComponent = class ButtonComponent {
|
|
|
128
129
|
isSignal: true,
|
|
129
130
|
isRequired: false,
|
|
130
131
|
transformFunction: null
|
|
132
|
+
},
|
|
133
|
+
flush: {
|
|
134
|
+
classPropertyName: "flush",
|
|
135
|
+
publicName: "flush",
|
|
136
|
+
isSignal: true,
|
|
137
|
+
isRequired: false,
|
|
138
|
+
transformFunction: null
|
|
131
139
|
}
|
|
132
140
|
},
|
|
133
141
|
outputs: {
|
|
@@ -142,8 +150,8 @@ var ButtonComponent = class ButtonComponent {
|
|
|
142
150
|
descendants: true
|
|
143
151
|
}],
|
|
144
152
|
ngImport: i0,
|
|
145
|
-
template: "<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n",
|
|
146
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"],
|
|
153
|
+
template: "<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline(),\n 'btn-flush': flush()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n",
|
|
154
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"],
|
|
147
155
|
dependencies: [{
|
|
148
156
|
kind: "directive",
|
|
149
157
|
type: NgClass,
|
|
@@ -167,8 +175,8 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
167
175
|
imports: [NgClass],
|
|
168
176
|
encapsulation: ViewEncapsulation.None,
|
|
169
177
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
170
|
-
template: "<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n",
|
|
171
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"]
|
|
178
|
+
template: "<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline(),\n 'btn-flush': flush()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n",
|
|
179
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"]
|
|
172
180
|
}]
|
|
173
181
|
}],
|
|
174
182
|
propDecorators: {
|
|
@@ -260,6 +268,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
260
268
|
required: false
|
|
261
269
|
}]
|
|
262
270
|
}],
|
|
271
|
+
flush: [{
|
|
272
|
+
type: i0.Input,
|
|
273
|
+
args: [{
|
|
274
|
+
isSignal: true,
|
|
275
|
+
alias: "flush",
|
|
276
|
+
required: false
|
|
277
|
+
}]
|
|
278
|
+
}],
|
|
263
279
|
clicked: [{
|
|
264
280
|
type: i0.Output,
|
|
265
281
|
args: ["clicked"]
|
|
@@ -284,6 +300,7 @@ var ButtonLinkComponent = class ButtonLinkComponent {
|
|
|
284
300
|
fullWidth = input(false, ...ngDevMode ? [{ debugName: "fullWidth" }] : /* istanbul ignore next */ []);
|
|
285
301
|
iconOnly = input(false, ...ngDevMode ? [{ debugName: "iconOnly" }] : /* istanbul ignore next */ []);
|
|
286
302
|
inline = input(false, ...ngDevMode ? [{ debugName: "inline" }] : /* istanbul ignore next */ []);
|
|
303
|
+
flush = input(false, ...ngDevMode ? [{ debugName: "flush" }] : /* istanbul ignore next */ []);
|
|
287
304
|
hostClasses = computed(() => {
|
|
288
305
|
const classes = [
|
|
289
306
|
"btn",
|
|
@@ -293,6 +310,7 @@ var ButtonLinkComponent = class ButtonLinkComponent {
|
|
|
293
310
|
if (this.iconOnly()) classes.push("btn-icon-only");
|
|
294
311
|
if (this.fullWidth()) classes.push("btn-full-width");
|
|
295
312
|
if (this.inline()) classes.push("btn-inline");
|
|
313
|
+
if (this.flush()) classes.push("btn-flush");
|
|
296
314
|
return classes.join(" ");
|
|
297
315
|
}, ...ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []);
|
|
298
316
|
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
@@ -344,6 +362,13 @@ var ButtonLinkComponent = class ButtonLinkComponent {
|
|
|
344
362
|
isSignal: true,
|
|
345
363
|
isRequired: false,
|
|
346
364
|
transformFunction: null
|
|
365
|
+
},
|
|
366
|
+
flush: {
|
|
367
|
+
classPropertyName: "flush",
|
|
368
|
+
publicName: "flush",
|
|
369
|
+
isSignal: true,
|
|
370
|
+
isRequired: false,
|
|
371
|
+
transformFunction: null
|
|
347
372
|
}
|
|
348
373
|
},
|
|
349
374
|
host: { properties: { "class": "hostClasses()" } },
|
|
@@ -352,7 +377,7 @@ var ButtonLinkComponent = class ButtonLinkComponent {
|
|
|
352
377
|
select="[slot='icon-after']"
|
|
353
378
|
/>`,
|
|
354
379
|
isInline: true,
|
|
355
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"],
|
|
380
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"],
|
|
356
381
|
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
357
382
|
encapsulation: i0.ViewEncapsulation.None
|
|
358
383
|
});
|
|
@@ -372,7 +397,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
372
397
|
encapsulation: ViewEncapsulation.None,
|
|
373
398
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
374
399
|
host: { "[class]": "hostClasses()" },
|
|
375
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"]
|
|
400
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:all var(--animation-duration-base) var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:break-word;-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"]
|
|
376
401
|
}]
|
|
377
402
|
}],
|
|
378
403
|
propDecorators: {
|
|
@@ -415,6 +440,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
415
440
|
alias: "inline",
|
|
416
441
|
required: false
|
|
417
442
|
}]
|
|
443
|
+
}],
|
|
444
|
+
flush: [{
|
|
445
|
+
type: i0.Input,
|
|
446
|
+
args: [{
|
|
447
|
+
isSignal: true,
|
|
448
|
+
alias: "flush",
|
|
449
|
+
required: false
|
|
450
|
+
}]
|
|
418
451
|
}]
|
|
419
452
|
}
|
|
420
453
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-button.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/button/button.component.ts","../../../../libs/angular-ui-kit/src/lib/button/button.component.html","../../../../libs/angular-ui-kit/src/lib/button/button-link.component.ts"],"sourcesContent":["import {\n Component,\n input,\n output,\n computed,\n ViewChild,\n ElementRef,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'outline'\n | 'ghost'\n | 'link'\n | 'danger'\n | 'warning'\n | 'info';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\nexport type ButtonType = 'button' | 'submit' | 'reset';\n\n@Component({\n selector: 'lc-button',\n standalone: true,\n imports: [NgClass],\n templateUrl: './button.component.html',\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None, // Required for dynamic variant class styling\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Button component for user actions and form submissions.\n *\n * Features:\n * - Multiple variants (primary, secondary, outline, ghost, danger, link)\n * - Size options (xs, sm, md, lg)\n * - Loading state with spinner\n * - Icon-only mode\n * - Full-width layout option\n * - Keyboard and focus handling\n * - Accessible with ARIA attributes\n *\n * @example\n * ```html\n * <lc-button variant=\"primary\" size=\"md\">Save</lc-button>\n * ```\n */\nexport class ButtonComponent {\n readonly variant = input<ButtonVariant>('primary');\n readonly size = input<ButtonSize>('md');\n readonly disabled = input(false);\n readonly loading = input(false);\n readonly iconOnly = input(false);\n readonly fullWidth = input(false);\n readonly ariaLabel = input('');\n readonly type = input<ButtonType>('button');\n\n /**\n * Native tooltip (title attribute) on the button.\n */\n readonly title = input('');\n\n /**\n * Reason shown as tooltip while the button is disabled (or loading).\n * Takes precedence over `title` in that state. The tooltip also appears\n * over the disabled button — the component guarantees the inner button\n * never gets `pointer-events: none`.\n */\n readonly disabledReason = input('');\n\n /**\n * Render as an inline text button that inherits font size, weight and\n * line-height from the surrounding text (for links inside copy, clickable\n * row titles, linked counters). Pair with `variant=\"link\"`.\n * @default false\n */\n readonly inline = input(false);\n\n readonly clicked = output<void>();\n readonly focused = output<void>();\n readonly blurred = output<void>();\n\n @ViewChild('buttonElement') buttonElement!: ElementRef<HTMLButtonElement>;\n\n readonly isDisabled = computed(() => this.disabled() || this.loading());\n\n /**\n * Tooltip actually applied to the button: `disabledReason` while disabled,\n * `title` otherwise.\n */\n readonly effectiveTitle = computed(() => {\n if (this.isDisabled() && this.disabledReason()) {\n return this.disabledReason();\n }\n return this.title() || null;\n });\n\n handleClick(): void {\n if (!this.isDisabled()) {\n this.clicked.emit();\n }\n }\n\n handleFocus(): void {\n this.focused.emit();\n }\n\n handleBlur(): void {\n this.blurred.emit();\n }\n\n focus(): void {\n this.buttonElement?.nativeElement.focus();\n }\n\n blur(): void {\n this.buttonElement?.nativeElement.blur();\n }\n}\n","<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n} from '@angular/core';\nimport type { ButtonSize, ButtonVariant } from './button.component';\n\n/**\n * `lc-button` styling on a native link: `<a lcButton href=\"…\">`.\n *\n * Use it for navigation that looks like a button — calls to action, \"read\n * more\" links, a language switch. The host *is* the anchor, so every native\n * link attribute (`href`, `hreflang`, `lang`, `rel`, `target`, `download`,\n * `title`, `aria-*`) passes through untouched, and the component adds no event\n * listeners: after server-side rendering or prerendering the markup is a plain\n * `<a class=\"btn btn-primary btn-md\" href=\"…\">` that works without JavaScript.\n * `routerLink` can sit on the same anchor for in-app navigation.\n *\n * Same variants, sizes and modifiers as `lc-button` (it shares its stylesheet).\n * Use `size=\"lg\"` (48.5 px) where the link must meet the 44 px touch target. A link\n * cannot be disabled or busy — render plain text or an `lc-button` for those\n * states. An `iconOnly` link needs an `aria-label`.\n *\n * @example\n * ```html\n * <a lcButton variant=\"primary\" size=\"lg\" href=\"/de/neuigkeiten\">Schau uns beim Bauen zu</a>\n * <a lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * <a lcButton variant=\"outline\" href=\"https://www.linkedin.com/in/…\" rel=\"me\">\n * <lc-icon slot=\"icon-before\" name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n * LinkedIn\n * </a>\n * ```\n */\n@Component({\n // An attribute selector on purpose: the anchor must stay the element in the\n // DOM so native link behaviour and attributes are untouched.\n selector: 'a[lcButton]',\n template: `<ng-content select=\"[slot='icon-before']\" /><ng-content /><ng-content\n select=\"[slot='icon-after']\"\n />`,\n // The same stylesheet as lc-button: identical style text is registered once,\n // whichever of the two renders first.\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class ButtonLinkComponent {\n /** Visual variant, as on `lc-button`. */\n readonly variant = input<ButtonVariant>('primary');\n /** Size, as on `lc-button`. `lg` (48.5 px high) meets the 44 px touch target. */\n readonly size = input<ButtonSize>('md');\n /** Stretch the link to the full width of its container. */\n readonly fullWidth = input(false);\n /** Square icon-only link. Give the anchor an `aria-label`. */\n readonly iconOnly = input(false);\n /**\n * Flow with the surrounding text instead of forming a pill (inherits font\n * size, weight and line-height). Pair with `variant=\"link\"`.\n */\n readonly inline = input(false);\n\n /** Classes on the anchor; merged with the consumer's own `class`. */\n protected readonly hostClasses = computed(() => {\n const classes = ['btn', `btn-${this.variant()}`, `btn-${this.size()}`];\n if (this.iconOnly()) classes.push('btn-icon-only');\n if (this.fullWidth()) classes.push('btn-full-width');\n if (this.inline()) classes.push('btn-inline');\n return classes.join(' ');\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-button.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/button/button.component.ts","../../../../libs/angular-ui-kit/src/lib/button/button.component.html","../../../../libs/angular-ui-kit/src/lib/button/button-link.component.ts"],"sourcesContent":["import {\n Component,\n input,\n output,\n computed,\n ViewChild,\n ElementRef,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'outline'\n | 'ghost'\n | 'link'\n | 'danger'\n | 'warning'\n | 'info';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\nexport type ButtonType = 'button' | 'submit' | 'reset';\n\n@Component({\n selector: 'lc-button',\n standalone: true,\n imports: [NgClass],\n templateUrl: './button.component.html',\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None, // Required for dynamic variant class styling\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Button component for user actions and form submissions.\n *\n * Features:\n * - Multiple variants (primary, secondary, outline, ghost, danger, link)\n * - Size options (xs, sm, md, lg)\n * - Loading state with spinner\n * - Icon-only mode\n * - Full-width layout option\n * - Keyboard and focus handling\n * - Accessible with ARIA attributes\n *\n * @example\n * ```html\n * <lc-button variant=\"primary\" size=\"md\">Save</lc-button>\n * ```\n */\nexport class ButtonComponent {\n readonly variant = input<ButtonVariant>('primary');\n readonly size = input<ButtonSize>('md');\n readonly disabled = input(false);\n readonly loading = input(false);\n readonly iconOnly = input(false);\n readonly fullWidth = input(false);\n readonly ariaLabel = input('');\n readonly type = input<ButtonType>('button');\n\n /**\n * Native tooltip (title attribute) on the button.\n */\n readonly title = input('');\n\n /**\n * Reason shown as tooltip while the button is disabled (or loading).\n * Takes precedence over `title` in that state. The tooltip also appears\n * over the disabled button — the component guarantees the inner button\n * never gets `pointer-events: none`.\n */\n readonly disabledReason = input('');\n\n /**\n * Render as an inline text button that inherits font size, weight and\n * line-height from the surrounding text (for links inside copy, clickable\n * row titles, linked counters). Pair with `variant=\"link\"`.\n * @default false\n */\n readonly inline = input(false);\n\n /**\n * Drop the inline padding so a `variant=\"link\"` button sits flush with the\n * content edge: the label starts at the edge, and the button keeps its height\n * and a 44 × 44 px minimum target. At the end edge of a row, set the CSS\n * hook `--lc-btn-flush-align: end` (default `start`) on the host or an\n * ancestor: every line of the label then ends at the edge. Ignored on other\n * variants and with `iconOnly` (3.9, AS-26).\n * @default false\n */\n readonly flush = input(false);\n\n readonly clicked = output<void>();\n readonly focused = output<void>();\n readonly blurred = output<void>();\n\n @ViewChild('buttonElement') buttonElement!: ElementRef<HTMLButtonElement>;\n\n readonly isDisabled = computed(() => this.disabled() || this.loading());\n\n /**\n * Tooltip actually applied to the button: `disabledReason` while disabled,\n * `title` otherwise.\n */\n readonly effectiveTitle = computed(() => {\n if (this.isDisabled() && this.disabledReason()) {\n return this.disabledReason();\n }\n return this.title() || null;\n });\n\n handleClick(): void {\n if (!this.isDisabled()) {\n this.clicked.emit();\n }\n }\n\n handleFocus(): void {\n this.focused.emit();\n }\n\n handleBlur(): void {\n this.blurred.emit();\n }\n\n focus(): void {\n this.buttonElement?.nativeElement.focus();\n }\n\n blur(): void {\n this.buttonElement?.nativeElement.blur();\n }\n}\n","<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline(),\n 'btn-flush': flush()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n} from '@angular/core';\nimport type { ButtonSize, ButtonVariant } from './button.component';\n\n/**\n * `lc-button` styling on a native link: `<a lcButton href=\"…\">`.\n *\n * Use it for navigation that looks like a button — calls to action, \"read\n * more\" links, a language switch. The host *is* the anchor, so every native\n * link attribute (`href`, `hreflang`, `lang`, `rel`, `target`, `download`,\n * `title`, `aria-*`) passes through untouched, and the component adds no event\n * listeners: after server-side rendering or prerendering the markup is a plain\n * `<a class=\"btn btn-primary btn-md\" href=\"…\">` that works without JavaScript.\n * `routerLink` can sit on the same anchor for in-app navigation.\n *\n * Same variants, sizes and modifiers as `lc-button` (it shares its stylesheet).\n * Use `size=\"lg\"` (48.5 px) where the link must meet the 44 px touch target. A link\n * cannot be disabled or busy — render plain text or an `lc-button` for those\n * states. An `iconOnly` link needs an `aria-label`.\n *\n * @example\n * ```html\n * <a lcButton variant=\"primary\" size=\"lg\" href=\"/de/neuigkeiten\">Schau uns beim Bauen zu</a>\n * <a lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * <a lcButton variant=\"outline\" href=\"https://www.linkedin.com/in/…\" rel=\"me\">\n * <lc-icon slot=\"icon-before\" name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n * LinkedIn\n * </a>\n * ```\n */\n@Component({\n // An attribute selector on purpose: the anchor must stay the element in the\n // DOM so native link behaviour and attributes are untouched.\n selector: 'a[lcButton]',\n template: `<ng-content select=\"[slot='icon-before']\" /><ng-content /><ng-content\n select=\"[slot='icon-after']\"\n />`,\n // The same stylesheet as lc-button: identical style text is registered once,\n // whichever of the two renders first.\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class ButtonLinkComponent {\n /** Visual variant, as on `lc-button`. */\n readonly variant = input<ButtonVariant>('primary');\n /** Size, as on `lc-button`. `lg` (48.5 px high) meets the 44 px touch target. */\n readonly size = input<ButtonSize>('md');\n /** Stretch the link to the full width of its container. */\n readonly fullWidth = input(false);\n /** Square icon-only link. Give the anchor an `aria-label`. */\n readonly iconOnly = input(false);\n /**\n * Flow with the surrounding text instead of forming a pill (inherits font\n * size, weight and line-height). Pair with `variant=\"link\"`.\n */\n readonly inline = input(false);\n /**\n * Drop the inline padding so a `variant=\"link\"` link sits flush with the\n * content edge: the label starts at the edge, and the link keeps its height\n * and a 44 × 44 px minimum target. At the end edge of a row, set the CSS\n * hook `--lc-btn-flush-align: end` (default `start`) on the link or an\n * ancestor: every line of the label then ends at the edge. Ignored on other\n * variants and with `iconOnly` (3.9, AS-26).\n * @default false\n */\n readonly flush = input(false);\n\n /** Classes on the anchor; merged with the consumer's own `class`. */\n protected readonly hostClasses = computed(() => {\n const classes = ['btn', `btn-${this.variant()}`, `btn-${this.size()}`];\n if (this.iconOnly()) classes.push('btn-icon-only');\n if (this.fullWidth()) classes.push('btn-full-width');\n if (this.inline()) classes.push('btn-inline');\n if (this.flush()) classes.push('btn-flush');\n return classes.join(' ');\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-choice-prompt.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.ts","../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n effect,\n input,\n isDevMode,\n output,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\n\n/** One selectable answer of an `lc-choice-prompt`. */\nexport interface ChoicePromptOption {\n id: string;\n label: string;\n /** Optional second line inside the option button. */\n description?: string;\n /** Marks the recommended answer: badge + first position. */\n recommended?: boolean;\n}\n\n/** A subordinate exit of the prompt (e.g. \"Selbst gelöst\" / \"Ignorieren\"). */\nexport interface ChoicePromptSecondaryAction {\n id: string;\n label: string;\n tooltip?: string;\n}\n\n/** Payload of the `(decided)` output — exactly one of the two fields is set. */\nexport interface ChoicePromptDecision {\n optionId?: string;\n customText?: string;\n}\n\nexport type ChoicePromptSize = 'sm' | 'md';\n\n/**\n * Inline decision prompt: predefined answer options (with a marked\n * recommendation) plus an optional free-text answer — no modal, directly in\n * the flow.\n *\n * Features:\n * - Options as buttons; `recommended` carries the badge and is sorted first\n * - Free-text lane behind a toggle link (`allowCustom`), submit via button or\n * Enter; empty text is never submittable\n * - `busy` after a decision: the clicked option shows a spinner, everything\n * else is disabled — prevents double submits. Focus stays on the triggering\n * element when `busy` ends.\n * - `disabled` requires a `disabledReason` (tooltip); missing reason logs a\n * dev warning\n * - Subordinate exits via `secondaryActions`\n * - `role=\"group\"` labelled via `promptLabel` (the question itself lives in\n * the surrounding layout)\n *\n * @example\n * ```html\n * <lc-choice-prompt\n * promptLabel=\"Wie soll der Konflikt gelöst werden?\"\n * [options]=\"[\n * { id: 'a', label: 'Variante A übernehmen', recommended: true },\n * { id: 'b', label: 'Beide behalten' },\n * ]\"\n * [busy]=\"saving()\"\n * (decided)=\"resolve($event)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-choice-prompt',\n standalone: true,\n imports: [ButtonComponent],\n templateUrl: './choice-prompt.component.html',\n styleUrls: ['./choice-prompt.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ChoicePromptComponent {\n /** Answer options. The recommended option is sorted to the front. */\n options = input.required<ChoicePromptOption[]>();\n\n /**\n * Whether the free-text lane is offered.\n * @default true\n */\n allowCustom = input<boolean>(true);\n\n /** Label of the link that opens the free-text lane. */\n customToggleLabel = input<string>('Eigene Antwort …');\n\n /** Placeholder of the free-text input. */\n customPlaceholder = input<string>('');\n\n /** Label of the free-text submit button. */\n submitLabel = input<string>('Übernehmen');\n\n /**\n * Set after a decision while it is being processed: the chosen element shows\n * a spinner, every other interaction is blocked (including Enter in the\n * free-text input).\n * @default false\n */\n busy = input<boolean>(false);\n\n /** Disables the whole prompt. Requires `disabledReason`. */\n disabled = input<boolean>(false);\n\n /** Why the prompt is disabled — shown as tooltip. */\n disabledReason = input<string>('');\n\n /** Subordinate exits, rendered as quiet text buttons after the options. */\n secondaryActions = input<ChoicePromptSecondaryAction[]>([]);\n\n /**\n * `sm` for dense lists (inbox rows).\n * @default 'md'\n */\n size = input<ChoicePromptSize>('md');\n\n /** Accessible name of the group — the question shown in the surroundings. */\n promptLabel = input<string>('');\n\n /** Label of the recommendation badge. */\n recommendedLabel = input<string>('Empfehlung');\n\n /** Fires immediately on option click, or on free-text submit. */\n decided = output<ChoicePromptDecision>();\n\n /** Fires with the id of a clicked secondary action. */\n secondaryAction = output<string>();\n\n /** Whether the free-text lane is open. */\n protected customOpen = signal(false);\n\n /** Current free-text value. */\n protected customText = signal('');\n\n /** Option that triggered the pending decision (spinner + focus anchor). */\n protected pendingOptionId = signal<string | null>(null);\n\n /** Whether the pending decision came from the free-text lane. */\n protected pendingCustom = signal(false);\n\n private customInput = viewChild<ElementRef<HTMLInputElement>>('customInput');\n private optionButtons = viewChildren<ElementRef<HTMLButtonElement>>('optionButton');\n private submitButton = viewChild<ButtonComponent>('submitButton');\n\n /** Options with the recommended one(s) first, original order otherwise. */\n protected sortedOptions = computed(() => {\n const options = this.options();\n return [...options.filter((o) => o.recommended), ...options.filter((o) => !o.recommended)];\n });\n\n /** No interaction while busy or disabled. */\n protected locked = computed(() => this.busy() || this.disabled());\n\n protected canSubmitCustom = computed(\n () => this.customText().trim().length > 0 && !this.locked(),\n );\n\n protected disabledTitle = computed(() =>\n this.disabled() && this.disabledReason() ? this.disabledReason() : null,\n );\n\n protected groupClasses = computed(() =>\n ['lc-choice-prompt', `lc-choice-prompt--${this.size()}`].join(' '),\n );\n\n constructor() {\n effect(() => {\n if (isDevMode() && this.disabled() && !this.disabledReason()) {\n console.warn(\n '[lc-choice-prompt] `disabled` is set without a `disabledReason`. ' +\n 'A disabled prompt must explain why (shown as tooltip).',\n );\n }\n });\n\n // When busy ends, focus returns to the element that triggered the\n // decision, then the pending markers reset.\n let wasBusy = false;\n effect(() => {\n const busy = this.busy();\n if (wasBusy && !busy) {\n this.restoreFocus();\n this.pendingOptionId.set(null);\n this.pendingCustom.set(false);\n }\n wasBusy = busy;\n });\n }\n\n protected isPendingOption(id: string): boolean {\n return this.busy() && this.pendingOptionId() === id;\n }\n\n protected chooseOption(option: ChoicePromptOption): void {\n if (this.locked()) return;\n this.pendingOptionId.set(option.id);\n this.pendingCustom.set(false);\n this.decided.emit({ optionId: option.id });\n }\n\n protected openCustom(): void {\n if (this.locked()) return;\n this.customOpen.set(true);\n // Focus the input once it is rendered.\n setTimeout(() => this.customInput()?.nativeElement.focus());\n }\n\n protected onCustomInput(event: Event): void {\n this.customText.set((event.target as HTMLInputElement).value);\n }\n\n protected submitCustom(): void {\n const text = this.customText().trim();\n if (!text || this.locked()) return;\n this.pendingCustom.set(true);\n this.pendingOptionId.set(null);\n this.decided.emit({ customText: text });\n }\n\n protected triggerSecondary(action: ChoicePromptSecondaryAction): void {\n if (this.locked()) return;\n this.secondaryAction.emit(action.id);\n }\n\n private restoreFocus(): void {\n const pendingId = this.pendingOptionId();\n if (pendingId !== null) {\n const button = this.optionButtons().find(\n (ref) => ref.nativeElement.dataset['optionId'] === pendingId,\n );\n button?.nativeElement.focus();\n } else if (this.pendingCustom()) {\n this.submitButton()?.focus();\n }\n }\n}\n","<div\n [class]=\"groupClasses()\"\n role=\"group\"\n [attr.aria-label]=\"promptLabel() || null\"\n [attr.aria-busy]=\"busy() ? 'true' : null\"\n>\n <div class=\"lc-choice-prompt__options\">\n @for (option of sortedOptions(); track option.id) {\n <!-- The busy (clicked) option keeps focus: aria-disabled instead of the\n native attribute, the click handler is guarded via locked(). -->\n <button\n #optionButton\n type=\"button\"\n class=\"lc-choice-prompt__option\"\n [class.lc-choice-prompt__option--recommended]=\"option.recommended\"\n [class.lc-choice-prompt__option--busy]=\"isPendingOption(option.id)\"\n [attr.data-option-id]=\"option.id\"\n [disabled]=\"locked() && !isPendingOption(option.id)\"\n [attr.aria-disabled]=\"locked() ? 'true' : null\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"chooseOption(option)\"\n >\n <span class=\"lc-choice-prompt__option-main\">\n @if (isPendingOption(option.id)) {\n <span class=\"lc-choice-prompt__spinner\" aria-hidden=\"true\"></span>\n }\n <span class=\"lc-choice-prompt__option-label\">{{ option.label }}</span>\n @if (option.recommended) {\n <span class=\"lc-choice-prompt__badge\">{{ recommendedLabel() }}</span>\n }\n </span>\n @if (option.description) {\n <span class=\"lc-choice-prompt__option-description\">{{ option.description }}</span>\n }\n </button>\n }\n\n @if (allowCustom() && !customOpen()) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__custom-toggle\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"openCustom()\"\n >\n {{ customToggleLabel() }}\n </button>\n }\n\n @for (action of secondaryActions(); track action.id) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__secondary\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle() ?? action.tooltip ?? null\"\n (click)=\"triggerSecondary(action)\"\n >\n {{ action.label }}\n </button>\n }\n </div>\n\n @if (allowCustom() && customOpen()) {\n <div class=\"lc-choice-prompt__custom\">\n <input\n #customInput\n type=\"text\"\n class=\"lc-choice-prompt__input\"\n [placeholder]=\"customPlaceholder()\"\n [value]=\"customText()\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n [attr.aria-label]=\"customToggleLabel()\"\n (input)=\"onCustomInput($event)\"\n (keydown.enter)=\"submitCustom()\"\n />\n <lc-button\n #submitButton\n variant=\"primary\"\n [size]=\"size() === 'sm' ? 'xs' : 'sm'\"\n [loading]=\"busy() && pendingCustom()\"\n [disabled]=\"!canSubmitCustom()\"\n [disabledReason]=\"disabledTitle() ?? ''\"\n (clicked)=\"submitCustom()\"\n >\n {{ submitLabel() }}\n </lc-button>\n </div>\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-choice-prompt.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.ts","../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n effect,\n input,\n isDevMode,\n output,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\n\n/** One selectable answer of an `lc-choice-prompt`. */\nexport interface ChoicePromptOption {\n id: string;\n label: string;\n /** Optional second line inside the option button. */\n description?: string;\n /** Marks the recommended answer: badge + first position. */\n recommended?: boolean;\n}\n\n/** A subordinate exit of the prompt (e.g. \"Selbst gelöst\" / \"Ignorieren\"). */\nexport interface ChoicePromptSecondaryAction {\n id: string;\n label: string;\n tooltip?: string;\n}\n\n/** Payload of the `(decided)` output — exactly one of the two fields is set. */\nexport interface ChoicePromptDecision {\n optionId?: string;\n customText?: string;\n}\n\nexport type ChoicePromptSize = 'sm' | 'md';\n\n/**\n * Inline decision prompt: predefined answer options (with a marked\n * recommendation) plus an optional free-text answer — no modal, directly in\n * the flow.\n *\n * Features:\n * - Options as buttons; `recommended` carries the badge and is sorted first\n * - Free-text lane behind a toggle link (`allowCustom`), submit via button or\n * Enter; empty text is never submittable\n * - `busy` after a decision: the clicked option shows a spinner, everything\n * else is disabled — prevents double submits. Focus stays on the triggering\n * element when `busy` ends.\n * - `disabled` requires a `disabledReason` (tooltip); missing reason logs a\n * dev warning\n * - Subordinate exits via `secondaryActions`\n * - `role=\"group\"` labelled via `promptLabel` (the question itself lives in\n * the surrounding layout)\n *\n * @example\n * ```html\n * <lc-choice-prompt\n * promptLabel=\"Wie soll der Konflikt gelöst werden?\"\n * [options]=\"[\n * { id: 'a', label: 'Variante A übernehmen', recommended: true },\n * { id: 'b', label: 'Beide behalten' },\n * ]\"\n * [busy]=\"saving()\"\n * (decided)=\"resolve($event)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-choice-prompt',\n standalone: true,\n imports: [ButtonComponent],\n templateUrl: './choice-prompt.component.html',\n styleUrls: ['./choice-prompt.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ChoicePromptComponent {\n /** Answer options. The recommended option is sorted to the front. */\n options = input.required<ChoicePromptOption[]>();\n\n /**\n * Whether the free-text lane is offered.\n * @default true\n */\n allowCustom = input<boolean>(true);\n\n /** Label of the link that opens the free-text lane. */\n customToggleLabel = input<string>('Eigene Antwort …');\n\n /** Placeholder of the free-text input. */\n customPlaceholder = input<string>('');\n\n /** Label of the free-text submit button. */\n submitLabel = input<string>('Übernehmen');\n\n /**\n * Set after a decision while it is being processed: the chosen element shows\n * a spinner, every other interaction is blocked (including Enter in the\n * free-text input).\n * @default false\n */\n busy = input<boolean>(false);\n\n /** Disables the whole prompt. Requires `disabledReason`. */\n disabled = input<boolean>(false);\n\n /** Why the prompt is disabled — shown as tooltip. */\n disabledReason = input<string>('');\n\n /** Subordinate exits, rendered as quiet text buttons after the options. */\n secondaryActions = input<ChoicePromptSecondaryAction[]>([]);\n\n /**\n * `sm` for dense lists (inbox rows).\n * @default 'md'\n */\n size = input<ChoicePromptSize>('md');\n\n /** Accessible name of the group — the question shown in the surroundings. */\n promptLabel = input<string>('');\n\n /** Label of the recommendation badge. */\n recommendedLabel = input<string>('Empfehlung');\n\n /** Fires immediately on option click, or on free-text submit. */\n decided = output<ChoicePromptDecision>();\n\n /** Fires with the id of a clicked secondary action. */\n secondaryAction = output<string>();\n\n /** Whether the free-text lane is open. */\n protected customOpen = signal(false);\n\n /** Current free-text value. */\n protected customText = signal('');\n\n /** Option that triggered the pending decision (spinner + focus anchor). */\n protected pendingOptionId = signal<string | null>(null);\n\n /** Whether the pending decision came from the free-text lane. */\n protected pendingCustom = signal(false);\n\n private customInput = viewChild<ElementRef<HTMLInputElement>>('customInput');\n private optionButtons = viewChildren<ElementRef<HTMLButtonElement>>('optionButton');\n private submitButton = viewChild<ButtonComponent>('submitButton');\n\n /** Options with the recommended one(s) first, original order otherwise. */\n protected sortedOptions = computed(() => {\n const options = this.options();\n return [...options.filter((o) => o.recommended), ...options.filter((o) => !o.recommended)];\n });\n\n /** No interaction while busy or disabled. */\n protected locked = computed(() => this.busy() || this.disabled());\n\n protected canSubmitCustom = computed(\n () => this.customText().trim().length > 0 && !this.locked(),\n );\n\n protected disabledTitle = computed(() =>\n this.disabled() && this.disabledReason() ? this.disabledReason() : null,\n );\n\n protected groupClasses = computed(() =>\n ['lc-choice-prompt', `lc-choice-prompt--${this.size()}`].join(' '),\n );\n\n constructor() {\n effect(() => {\n if (isDevMode() && this.disabled() && !this.disabledReason()) {\n console.warn(\n '[lc-choice-prompt] `disabled` is set without a `disabledReason`. ' +\n 'A disabled prompt must explain why (shown as tooltip).',\n );\n }\n });\n\n // When busy ends, focus returns to the element that triggered the\n // decision, then the pending markers reset.\n let wasBusy = false;\n effect(() => {\n const busy = this.busy();\n if (wasBusy && !busy) {\n this.restoreFocus();\n this.pendingOptionId.set(null);\n this.pendingCustom.set(false);\n }\n wasBusy = busy;\n });\n }\n\n protected isPendingOption(id: string): boolean {\n return this.busy() && this.pendingOptionId() === id;\n }\n\n protected chooseOption(option: ChoicePromptOption): void {\n if (this.locked()) return;\n this.pendingOptionId.set(option.id);\n this.pendingCustom.set(false);\n this.decided.emit({ optionId: option.id });\n }\n\n protected openCustom(): void {\n if (this.locked()) return;\n this.customOpen.set(true);\n // Focus the input once it is rendered.\n setTimeout(() => this.customInput()?.nativeElement.focus());\n }\n\n protected onCustomInput(event: Event): void {\n this.customText.set((event.target as HTMLInputElement).value);\n }\n\n protected submitCustom(): void {\n const text = this.customText().trim();\n if (!text || this.locked()) return;\n this.pendingCustom.set(true);\n this.pendingOptionId.set(null);\n this.decided.emit({ customText: text });\n }\n\n protected triggerSecondary(action: ChoicePromptSecondaryAction): void {\n if (this.locked()) return;\n this.secondaryAction.emit(action.id);\n }\n\n private restoreFocus(): void {\n const pendingId = this.pendingOptionId();\n if (pendingId !== null) {\n const button = this.optionButtons().find(\n (ref) => ref.nativeElement.dataset['optionId'] === pendingId,\n );\n button?.nativeElement.focus();\n } else if (this.pendingCustom()) {\n this.submitButton()?.focus();\n }\n }\n}\n","<div\n [class]=\"groupClasses()\"\n role=\"group\"\n [attr.aria-label]=\"promptLabel() || null\"\n [attr.aria-busy]=\"busy() ? 'true' : null\"\n>\n <div class=\"lc-choice-prompt__options\">\n @for (option of sortedOptions(); track option.id) {\n <!-- The busy (clicked) option keeps focus: aria-disabled instead of the\n native attribute, the click handler is guarded via locked(). -->\n <button\n #optionButton\n type=\"button\"\n class=\"lc-choice-prompt__option\"\n [class.lc-choice-prompt__option--recommended]=\"option.recommended\"\n [class.lc-choice-prompt__option--busy]=\"isPendingOption(option.id)\"\n [attr.data-option-id]=\"option.id\"\n [disabled]=\"locked() && !isPendingOption(option.id)\"\n [attr.aria-disabled]=\"locked() ? 'true' : null\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"chooseOption(option)\"\n >\n <span class=\"lc-choice-prompt__option-main\">\n @if (isPendingOption(option.id)) {\n <span class=\"lc-choice-prompt__spinner\" aria-hidden=\"true\"></span>\n }\n <span class=\"lc-choice-prompt__option-label\">{{ option.label }}</span>\n @if (option.recommended) {\n <span class=\"lc-choice-prompt__badge\">{{ recommendedLabel() }}</span>\n }\n </span>\n @if (option.description) {\n <span class=\"lc-choice-prompt__option-description\">{{ option.description }}</span>\n }\n </button>\n }\n\n @if (allowCustom() && !customOpen()) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__custom-toggle\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"openCustom()\"\n >\n {{ customToggleLabel() }}\n </button>\n }\n\n @for (action of secondaryActions(); track action.id) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__secondary\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle() ?? action.tooltip ?? null\"\n (click)=\"triggerSecondary(action)\"\n >\n {{ action.label }}\n </button>\n }\n </div>\n\n @if (allowCustom() && customOpen()) {\n <div class=\"lc-choice-prompt__custom\">\n <input\n #customInput\n type=\"text\"\n class=\"lc-choice-prompt__input\"\n [placeholder]=\"customPlaceholder()\"\n [value]=\"customText()\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n [attr.aria-label]=\"customToggleLabel()\"\n (input)=\"onCustomInput($event)\"\n (keydown.enter)=\"submitCustom()\"\n />\n <lc-button\n #submitButton\n variant=\"primary\"\n [size]=\"size() === 'sm' ? 'xs' : 'sm'\"\n [loading]=\"busy() && pendingCustom()\"\n [disabled]=\"!canSubmitCustom()\"\n [disabledReason]=\"disabledTitle() ?? ''\"\n (clicked)=\"submitCustom()\"\n >\n {{ submitLabel() }}\n </lc-button>\n </div>\n }\n</div>\n"],"mappings":"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"}
|