@lifecorner/angular-ui-kit 3.24.0 → 3.25.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-accordion.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-accordion.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-code-block.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-code-block.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs +7 -7
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs +12 -4
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-password-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-password-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-progress-bar.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-slider.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-slider.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-tree-view.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-tree-view.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-verification-code-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-verification-code-input.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/theme-contrast.spec.ts +235 -7
- package/types/lifecorner-angular-ui-kit-accordion.d.ts +3 -1
- package/types/lifecorner-angular-ui-kit-description-list.d.ts +17 -5
|
@@ -221,7 +221,7 @@ var AccordionComponent = class AccordionComponent {
|
|
|
221
221
|
}],
|
|
222
222
|
ngImport: i0,
|
|
223
223
|
template: "<div [class]=\"accordionClasses()\">\n <!-- The heading wrapper gives the disclosure button a heading level (WAI-ARIA accordion pattern). -->\n <div class=\"lc-accordion__heading\" role=\"heading\" [attr.aria-level]=\"headingLevel()\">\n <button\n class=\"lc-accordion__header\"\n type=\"button\"\n [id]=\"headerId\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-label]=\"headerAriaLabel()\"\n [attr.aria-labelledby]=\"headerLabelledBy()\"\n [attr.aria-disabled]=\"disabled()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (headerTemplate(); as header) {\n <!-- The label starts the name and the template's text follows it, so\n the name contains what is shown (WCAG 2.5.3). -->\n @if (richHeaderLabel()) {\n <span hidden [id]=\"headerId + '-label'\">{{ richHeaderLabel() }},</span>\n }\n <span class=\"lc-accordion__header-content\" [attr.id]=\"richHeaderLabel() ? headerId + '-content' : null\">\n <ng-container *ngTemplateOutlet=\"header.template\"></ng-container>\n </span>\n } @else {\n <span class=\"lc-accordion__title\">{{ title() }}</span>\n }\n <lc-icon\n class=\"lc-accordion__icon\"\n name=\"chevron-down\"\n size=\"sm\"\n [decorative]=\"true\"\n ></lc-icon>\n </button>\n </div>\n\n <!--\n A collapsed panel is `inert`: its eagerly projected body stays in the DOM\n (for the height animation) but is neither focusable nor exposed to AT.\n -->\n <div\n class=\"lc-accordion__panel\"\n [id]=\"panelId\"\n role=\"region\"\n [attr.aria-labelledby]=\"headerLabelledBy() ?? headerId\"\n [attr.aria-hidden]=\"!expanded()\"\n [attr.inert]=\"expanded() ? null : ''\"\n >\n <div class=\"lc-accordion__body\">\n @if (contentTemplate(); as content) {\n @if (shouldRenderBody()) {\n <ng-container *ngTemplateOutlet=\"content.template\"></ng-container>\n }\n } @else {\n <ng-content></ng-content>\n }\n </div>\n </div>\n</div>\n",
|
|
224
|
-
styles: [":host{display:block}.lc-accordion{border-radius:var(--border-radius-lg);overflow:hidden;transition:box-shadow .2s ease,border-color .2s ease}.lc-accordion--outlined{border:1px solid var(--lc-accordion-border, var(--color-border));background:var(--color-surface);box-shadow:var(--elevation-1)}.lc-accordion--outlined:hover:not(.lc-accordion--disabled){box-shadow:var(--elevation-1)}.lc-accordion--flat{border:none;background:transparent}.lc-accordion--disabled{opacity:.5;pointer-events:none}.lc-accordion__heading{display:block;margin:0}.lc-accordion__header{display:flex;width:100%;align-items:center;justify-content:space-between;gap:.75rem;padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-weight:600;letter-spacing:-.01em;color:var(--lc-accordion-header-fg, var(--color-text-primary));background:var(--lc-accordion-header-bg, transparent);border:var(--lc-accordion-header-border, none);border-radius:0;cursor:pointer;transition:background-color .15s ease,color .15s ease}.lc-accordion__header:hover{background-color:var(--lc-accordion-header-hover-bg, var(--color-surface-hover))}.lc-accordion__header:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px;border-radius:var(--border-radius-md)}.lc-accordion__header:disabled{cursor:not-allowed}.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem .875rem);font-size:.8125rem}.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-size:.9375rem}.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 1.375rem);font-size:1.0625rem}.lc-accordion__title{flex:1;text-align:left}.lc-accordion__header-content{display:flex;flex:1;min-width:0;align-items:center;gap:.75rem;text-align:left;font-weight:inherit}.lc-accordion__icon{flex-shrink:0;color:var(--color-text-secondary);transition:transform .3s cubic-bezier(.25,.46,.45,.94),color .2s ease}.lc-accordion--chevron-leading .lc-accordion__icon{order:-1}.lc-accordion__header:hover .lc-accordion__icon{color:var(--color-text-primary)}.lc-accordion--expanded .lc-accordion__icon{transform:rotate(-180deg)}.lc-accordion__panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.25,.46,.45,.94);overflow:hidden}.lc-accordion--expanded .lc-accordion__panel{grid-template-rows:1fr}.lc-accordion__body{min-height:0;overflow:hidden;padding:0 1.125rem;color:var(--color-text-secondary);font-size:.875rem;line-height:1.6;opacity:0;transform:translateY(-4px);visibility:hidden;transition:opacity .2s ease 50ms,transform .2s ease 50ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s linear .3s}.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .875rem 1.125rem 1rem);opacity:1;transform:translateY(0);visibility:visible;transition:opacity .25s ease 80ms,transform .25s ease 80ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s}.lc-accordion--sm .lc-accordion__body{padding:0 .875rem;font-size:.8125rem}.lc-accordion--sm.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .625rem .875rem .75rem)}.lc-accordion--lg .lc-accordion__body{padding:0 1.375rem;font-size:.9375rem}.lc-accordion--lg.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, 1rem 1.375rem 1.25rem)}.lc-accordion--plain{border:none;background:transparent;overflow:visible}.lc-accordion--plain .lc-accordion__header{position:relative;isolation:isolate;min-height:var(--size-min-touch-height, 2.75rem);background:transparent;border:none}.lc-accordion--plain.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem 0)}.lc-accordion--plain.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 0)}.lc-accordion--plain.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 0)}.lc-accordion--plain .lc-accordion__header:hover{background-color:transparent}.lc-accordion--plain .lc-accordion__header:focus-visible{outline:none}.lc-accordion--plain .lc-accordion__header:before{content:\"\";position:absolute;inset-block:0;inset-inline:calc(-1 * var(--
|
|
224
|
+
styles: [":host{display:block}.lc-accordion{border-radius:var(--border-radius-lg);overflow:hidden;transition:box-shadow .2s ease,border-color .2s ease}.lc-accordion--outlined{border:1px solid var(--lc-accordion-border, var(--color-border));background:var(--color-surface);box-shadow:var(--elevation-1)}.lc-accordion--outlined:hover:not(.lc-accordion--disabled){box-shadow:var(--elevation-1)}.lc-accordion--flat{border:none;background:transparent}.lc-accordion--disabled{opacity:.5;pointer-events:none}.lc-accordion__heading{display:block;margin:0}.lc-accordion__header{display:flex;width:100%;align-items:center;justify-content:space-between;gap:.75rem;padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-weight:600;letter-spacing:-.01em;color:var(--lc-accordion-header-fg, var(--color-text-primary));background:var(--lc-accordion-header-bg, transparent);border:var(--lc-accordion-header-border, none);border-radius:0;cursor:pointer;transition:background-color .15s ease,color .15s ease}.lc-accordion__header:hover{background-color:var(--lc-accordion-header-hover-bg, var(--color-surface-hover))}.lc-accordion__header:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px;border-radius:var(--border-radius-md)}.lc-accordion__header:disabled{cursor:not-allowed}.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem .875rem);font-size:.8125rem}.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-size:.9375rem}.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 1.375rem);font-size:1.0625rem}.lc-accordion__title{flex:1;text-align:left}.lc-accordion__header-content{display:flex;flex:1;min-width:0;align-items:center;gap:.75rem;text-align:left;font-weight:inherit}.lc-accordion__icon{flex-shrink:0;color:var(--color-text-secondary);transition:transform .3s cubic-bezier(.25,.46,.45,.94),color .2s ease}.lc-accordion--chevron-leading .lc-accordion__icon{order:-1}.lc-accordion__header:hover .lc-accordion__icon{color:var(--color-text-primary)}.lc-accordion--expanded .lc-accordion__icon{transform:rotate(-180deg)}.lc-accordion__panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.25,.46,.45,.94);overflow:hidden}.lc-accordion--expanded .lc-accordion__panel{grid-template-rows:1fr}.lc-accordion__body{min-height:0;overflow:hidden;padding:0 1.125rem;color:var(--color-text-secondary);font-size:.875rem;line-height:1.6;opacity:0;transform:translateY(-4px);visibility:hidden;transition:opacity .2s ease 50ms,transform .2s ease 50ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s linear .3s}.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .875rem 1.125rem 1rem);opacity:1;transform:translateY(0);visibility:visible;transition:opacity .25s ease 80ms,transform .25s ease 80ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s}.lc-accordion--sm .lc-accordion__body{padding:0 .875rem;font-size:.8125rem}.lc-accordion--sm.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .625rem .875rem .75rem)}.lc-accordion--lg .lc-accordion__body{padding:0 1.375rem;font-size:.9375rem}.lc-accordion--lg.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, 1rem 1.375rem 1.25rem)}.lc-accordion--plain{border:none;background:transparent;overflow:visible}.lc-accordion--plain .lc-accordion__header{position:relative;isolation:isolate;min-height:var(--size-min-touch-height, 2.75rem);background:transparent;border:none}.lc-accordion--plain.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem 0)}.lc-accordion--plain.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 0)}.lc-accordion--plain.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 0)}.lc-accordion--plain .lc-accordion__header:hover{background-color:transparent}.lc-accordion--plain .lc-accordion__header:focus-visible{outline:none}@property --_lc-accordion-header-bleed{syntax: \"<length-percentage>\"; inherits: false; initial-value: 0px;}.lc-accordion--plain .lc-accordion__header:before{--_lc-accordion-header-bleed: var(--lc-accordion-header-bleed, var(--spacing-2));content:\"\";position:absolute;inset-block:0;inset-inline:calc(-1 * var(--_lc-accordion-header-bleed));z-index:-1;border:var(--lc-accordion-header-border, none);border-radius:var(--border-radius-md);background:var(--lc-accordion-header-bg, transparent);transition:background-color .15s ease}.lc-accordion--plain .lc-accordion__header:hover:before{background-color:var(--lc-accordion-header-hover-bg, var(--color-surface-hover))}.lc-accordion--plain .lc-accordion__header:focus-visible:before{outline:2px solid var(--color-primary);outline-offset:-2px}.lc-accordion--plain .lc-accordion__title{min-width:0;overflow-wrap:break-word;hyphens:auto;hyphenate-limit-chars:12 4 3;text-align:start}.lc-accordion--plain .lc-accordion__panel{overflow-x:visible;overflow-y:clip}.lc-accordion--plain .lc-accordion__body{padding:0;overflow-x:visible;overflow-y:clip}.lc-accordion--plain.lc-accordion--sm.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .625rem 0 .75rem)}.lc-accordion--plain.lc-accordion--md.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .875rem 0 1rem)}.lc-accordion--plain.lc-accordion--lg.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, 1rem 0 1.25rem)}@media(prefers-reduced-motion:reduce){.lc-accordion--plain .lc-accordion__header,.lc-accordion--plain .lc-accordion__header:before,.lc-accordion--plain .lc-accordion__icon,.lc-accordion--plain .lc-accordion__panel,.lc-accordion--plain .lc-accordion__body{transition:none}}@media(forced-colors:active){.lc-accordion--plain .lc-accordion__header:focus-visible:before{outline-color:Highlight}}\n"],
|
|
225
225
|
dependencies: [{
|
|
226
226
|
kind: "component",
|
|
227
227
|
type: IconComponent,
|
|
@@ -263,7 +263,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
263
263
|
viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_DOWN])],
|
|
264
264
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
265
265
|
template: "<div [class]=\"accordionClasses()\">\n <!-- The heading wrapper gives the disclosure button a heading level (WAI-ARIA accordion pattern). -->\n <div class=\"lc-accordion__heading\" role=\"heading\" [attr.aria-level]=\"headingLevel()\">\n <button\n class=\"lc-accordion__header\"\n type=\"button\"\n [id]=\"headerId\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-label]=\"headerAriaLabel()\"\n [attr.aria-labelledby]=\"headerLabelledBy()\"\n [attr.aria-disabled]=\"disabled()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (headerTemplate(); as header) {\n <!-- The label starts the name and the template's text follows it, so\n the name contains what is shown (WCAG 2.5.3). -->\n @if (richHeaderLabel()) {\n <span hidden [id]=\"headerId + '-label'\">{{ richHeaderLabel() }},</span>\n }\n <span class=\"lc-accordion__header-content\" [attr.id]=\"richHeaderLabel() ? headerId + '-content' : null\">\n <ng-container *ngTemplateOutlet=\"header.template\"></ng-container>\n </span>\n } @else {\n <span class=\"lc-accordion__title\">{{ title() }}</span>\n }\n <lc-icon\n class=\"lc-accordion__icon\"\n name=\"chevron-down\"\n size=\"sm\"\n [decorative]=\"true\"\n ></lc-icon>\n </button>\n </div>\n\n <!--\n A collapsed panel is `inert`: its eagerly projected body stays in the DOM\n (for the height animation) but is neither focusable nor exposed to AT.\n -->\n <div\n class=\"lc-accordion__panel\"\n [id]=\"panelId\"\n role=\"region\"\n [attr.aria-labelledby]=\"headerLabelledBy() ?? headerId\"\n [attr.aria-hidden]=\"!expanded()\"\n [attr.inert]=\"expanded() ? null : ''\"\n >\n <div class=\"lc-accordion__body\">\n @if (contentTemplate(); as content) {\n @if (shouldRenderBody()) {\n <ng-container *ngTemplateOutlet=\"content.template\"></ng-container>\n }\n } @else {\n <ng-content></ng-content>\n }\n </div>\n </div>\n</div>\n",
|
|
266
|
-
styles: [":host{display:block}.lc-accordion{border-radius:var(--border-radius-lg);overflow:hidden;transition:box-shadow .2s ease,border-color .2s ease}.lc-accordion--outlined{border:1px solid var(--lc-accordion-border, var(--color-border));background:var(--color-surface);box-shadow:var(--elevation-1)}.lc-accordion--outlined:hover:not(.lc-accordion--disabled){box-shadow:var(--elevation-1)}.lc-accordion--flat{border:none;background:transparent}.lc-accordion--disabled{opacity:.5;pointer-events:none}.lc-accordion__heading{display:block;margin:0}.lc-accordion__header{display:flex;width:100%;align-items:center;justify-content:space-between;gap:.75rem;padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-weight:600;letter-spacing:-.01em;color:var(--lc-accordion-header-fg, var(--color-text-primary));background:var(--lc-accordion-header-bg, transparent);border:var(--lc-accordion-header-border, none);border-radius:0;cursor:pointer;transition:background-color .15s ease,color .15s ease}.lc-accordion__header:hover{background-color:var(--lc-accordion-header-hover-bg, var(--color-surface-hover))}.lc-accordion__header:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px;border-radius:var(--border-radius-md)}.lc-accordion__header:disabled{cursor:not-allowed}.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem .875rem);font-size:.8125rem}.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-size:.9375rem}.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 1.375rem);font-size:1.0625rem}.lc-accordion__title{flex:1;text-align:left}.lc-accordion__header-content{display:flex;flex:1;min-width:0;align-items:center;gap:.75rem;text-align:left;font-weight:inherit}.lc-accordion__icon{flex-shrink:0;color:var(--color-text-secondary);transition:transform .3s cubic-bezier(.25,.46,.45,.94),color .2s ease}.lc-accordion--chevron-leading .lc-accordion__icon{order:-1}.lc-accordion__header:hover .lc-accordion__icon{color:var(--color-text-primary)}.lc-accordion--expanded .lc-accordion__icon{transform:rotate(-180deg)}.lc-accordion__panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.25,.46,.45,.94);overflow:hidden}.lc-accordion--expanded .lc-accordion__panel{grid-template-rows:1fr}.lc-accordion__body{min-height:0;overflow:hidden;padding:0 1.125rem;color:var(--color-text-secondary);font-size:.875rem;line-height:1.6;opacity:0;transform:translateY(-4px);visibility:hidden;transition:opacity .2s ease 50ms,transform .2s ease 50ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s linear .3s}.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .875rem 1.125rem 1rem);opacity:1;transform:translateY(0);visibility:visible;transition:opacity .25s ease 80ms,transform .25s ease 80ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s}.lc-accordion--sm .lc-accordion__body{padding:0 .875rem;font-size:.8125rem}.lc-accordion--sm.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .625rem .875rem .75rem)}.lc-accordion--lg .lc-accordion__body{padding:0 1.375rem;font-size:.9375rem}.lc-accordion--lg.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, 1rem 1.375rem 1.25rem)}.lc-accordion--plain{border:none;background:transparent;overflow:visible}.lc-accordion--plain .lc-accordion__header{position:relative;isolation:isolate;min-height:var(--size-min-touch-height, 2.75rem);background:transparent;border:none}.lc-accordion--plain.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem 0)}.lc-accordion--plain.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 0)}.lc-accordion--plain.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 0)}.lc-accordion--plain .lc-accordion__header:hover{background-color:transparent}.lc-accordion--plain .lc-accordion__header:focus-visible{outline:none}.lc-accordion--plain .lc-accordion__header:before{content:\"\";position:absolute;inset-block:0;inset-inline:calc(-1 * var(--
|
|
266
|
+
styles: [":host{display:block}.lc-accordion{border-radius:var(--border-radius-lg);overflow:hidden;transition:box-shadow .2s ease,border-color .2s ease}.lc-accordion--outlined{border:1px solid var(--lc-accordion-border, var(--color-border));background:var(--color-surface);box-shadow:var(--elevation-1)}.lc-accordion--outlined:hover:not(.lc-accordion--disabled){box-shadow:var(--elevation-1)}.lc-accordion--flat{border:none;background:transparent}.lc-accordion--disabled{opacity:.5;pointer-events:none}.lc-accordion__heading{display:block;margin:0}.lc-accordion__header{display:flex;width:100%;align-items:center;justify-content:space-between;gap:.75rem;padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-weight:600;letter-spacing:-.01em;color:var(--lc-accordion-header-fg, var(--color-text-primary));background:var(--lc-accordion-header-bg, transparent);border:var(--lc-accordion-header-border, none);border-radius:0;cursor:pointer;transition:background-color .15s ease,color .15s ease}.lc-accordion__header:hover{background-color:var(--lc-accordion-header-hover-bg, var(--color-surface-hover))}.lc-accordion__header:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px;border-radius:var(--border-radius-md)}.lc-accordion__header:disabled{cursor:not-allowed}.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem .875rem);font-size:.8125rem}.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 1.125rem);font-size:.9375rem}.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 1.375rem);font-size:1.0625rem}.lc-accordion__title{flex:1;text-align:left}.lc-accordion__header-content{display:flex;flex:1;min-width:0;align-items:center;gap:.75rem;text-align:left;font-weight:inherit}.lc-accordion__icon{flex-shrink:0;color:var(--color-text-secondary);transition:transform .3s cubic-bezier(.25,.46,.45,.94),color .2s ease}.lc-accordion--chevron-leading .lc-accordion__icon{order:-1}.lc-accordion__header:hover .lc-accordion__icon{color:var(--color-text-primary)}.lc-accordion--expanded .lc-accordion__icon{transform:rotate(-180deg)}.lc-accordion__panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s cubic-bezier(.25,.46,.45,.94);overflow:hidden}.lc-accordion--expanded .lc-accordion__panel{grid-template-rows:1fr}.lc-accordion__body{min-height:0;overflow:hidden;padding:0 1.125rem;color:var(--color-text-secondary);font-size:.875rem;line-height:1.6;opacity:0;transform:translateY(-4px);visibility:hidden;transition:opacity .2s ease 50ms,transform .2s ease 50ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s linear .3s}.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .875rem 1.125rem 1rem);opacity:1;transform:translateY(0);visibility:visible;transition:opacity .25s ease 80ms,transform .25s ease 80ms,padding .3s cubic-bezier(.25,.46,.45,.94),visibility 0s}.lc-accordion--sm .lc-accordion__body{padding:0 .875rem;font-size:.8125rem}.lc-accordion--sm.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .625rem .875rem .75rem)}.lc-accordion--lg .lc-accordion__body{padding:0 1.375rem;font-size:.9375rem}.lc-accordion--lg.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, 1rem 1.375rem 1.25rem)}.lc-accordion--plain{border:none;background:transparent;overflow:visible}.lc-accordion--plain .lc-accordion__header{position:relative;isolation:isolate;min-height:var(--size-min-touch-height, 2.75rem);background:transparent;border:none}.lc-accordion--plain.lc-accordion--sm .lc-accordion__header{padding:var(--lc-accordion-header-padding, .625rem 0)}.lc-accordion--plain.lc-accordion--md .lc-accordion__header{padding:var(--lc-accordion-header-padding, .875rem 0)}.lc-accordion--plain.lc-accordion--lg .lc-accordion__header{padding:var(--lc-accordion-header-padding, 1.125rem 0)}.lc-accordion--plain .lc-accordion__header:hover{background-color:transparent}.lc-accordion--plain .lc-accordion__header:focus-visible{outline:none}@property --_lc-accordion-header-bleed{syntax: \"<length-percentage>\"; inherits: false; initial-value: 0px;}.lc-accordion--plain .lc-accordion__header:before{--_lc-accordion-header-bleed: var(--lc-accordion-header-bleed, var(--spacing-2));content:\"\";position:absolute;inset-block:0;inset-inline:calc(-1 * var(--_lc-accordion-header-bleed));z-index:-1;border:var(--lc-accordion-header-border, none);border-radius:var(--border-radius-md);background:var(--lc-accordion-header-bg, transparent);transition:background-color .15s ease}.lc-accordion--plain .lc-accordion__header:hover:before{background-color:var(--lc-accordion-header-hover-bg, var(--color-surface-hover))}.lc-accordion--plain .lc-accordion__header:focus-visible:before{outline:2px solid var(--color-primary);outline-offset:-2px}.lc-accordion--plain .lc-accordion__title{min-width:0;overflow-wrap:break-word;hyphens:auto;hyphenate-limit-chars:12 4 3;text-align:start}.lc-accordion--plain .lc-accordion__panel{overflow-x:visible;overflow-y:clip}.lc-accordion--plain .lc-accordion__body{padding:0;overflow-x:visible;overflow-y:clip}.lc-accordion--plain.lc-accordion--sm.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .625rem 0 .75rem)}.lc-accordion--plain.lc-accordion--md.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, .875rem 0 1rem)}.lc-accordion--plain.lc-accordion--lg.lc-accordion--expanded .lc-accordion__body{padding:var(--lc-accordion-body-padding, 1rem 0 1.25rem)}@media(prefers-reduced-motion:reduce){.lc-accordion--plain .lc-accordion__header,.lc-accordion--plain .lc-accordion__header:before,.lc-accordion--plain .lc-accordion__icon,.lc-accordion--plain .lc-accordion__panel,.lc-accordion--plain .lc-accordion__body{transition:none}}@media(forced-colors:active){.lc-accordion--plain .lc-accordion__header:focus-visible:before{outline-color:Highlight}}\n"]
|
|
267
267
|
}]
|
|
268
268
|
}],
|
|
269
269
|
ctorParameters: () => [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-accordion.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/accordion/accordion-header.directive.ts","../../../../libs/angular-ui-kit/src/lib/accordion/accordion-content.directive.ts","../../../../libs/angular-ui-kit/src/lib/accordion/accordion.component.ts","../../../../libs/angular-ui-kit/src/lib/accordion/accordion.component.html","../../../../libs/angular-ui-kit/src/lib/accordion/accordion-group.component.ts"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\n\n/**\n * Marks an `<ng-template>` as the rich header content for an `<lc-accordion>`.\n *\n * When present, the projected template is rendered inside the header button\n * instead of the plain `title` string. The accordion still owns the disclosure\n * chevron, click/keyboard handling and focus ring — the consumer only supplies\n * the (non-interactive) inner content.\n *\n * A11y constraint: the header is itself a `<button>`, so the template must not\n * contain nested interactive elements (no button/link/input). Text, badges and\n * other non-interactive nodes only.\n *\n * Name (WCAG 2.5.3 Label in Name): the header is named by the template's\n * text; the accordion's `ariaLabel` (or `title`), if set, comes first through\n * `aria-labelledby`. Separate the template's parts with whitespace\n * (`&ngsp;`), so they read as words (\"Item label Done 12:04\"), and set a\n * label only for context that the template doesn't show.\n *\n * @example\n * ```html\n * <lc-accordion variant=\"flat\" chevronPosition=\"leading\">\n * <ng-template lcAccordionHeader>\n * <span class=\"title\">Item label</span>&ngsp;\n * <lc-badge variant=\"success\" size=\"sm\">Done</lc-badge>&ngsp;\n * <span style=\"margin-left: auto;\">12:04</span>\n * </ng-template>\n * <div>Body…</div>\n * </lc-accordion>\n * ```\n */\n@Directive({\n selector: '[lcAccordionHeader]',\n standalone: true,\n})\nexport class AccordionHeaderDirective {\n public readonly template = inject(TemplateRef<unknown>);\n}\n","import { Directive, TemplateRef, inject } from '@angular/core';\n\n/**\n * Marks an `<ng-template>` as the (optionally lazy) body content for an\n * `<lc-accordion>`.\n *\n * Unlike default `<ng-content>` projection — which Angular always instantiates\n * eagerly — a template referenced through this directive is only stamped out\n * when the accordion decides to render its body. That is what makes\n * `[lazy]=\"true\"` and `[destroyOnClose]=\"true\"` possible: expensive children\n * (HTTP-backed panels, charts, live-polling views) are not created until the\n * panel is first opened.\n *\n * @example\n * ```html\n * <lc-accordion [lazy]=\"true\">\n * <ng-template lcAccordionContent>\n * <expensive-panel [id]=\"id\" />\n * </ng-template>\n * </lc-accordion>\n * ```\n */\n@Directive({\n selector: '[lcAccordionContent]',\n standalone: true,\n})\nexport class AccordionContentDirective {\n public readonly template = inject(TemplateRef<unknown>);\n}\n","import {\n Component,\n ChangeDetectionStrategy,\n input,\n model,\n computed,\n signal,\n contentChild,\n effect,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHEVRON_DOWN } from '@lifecorner/angular-ui-kit/icons';\nimport { AccordionHeaderDirective } from './accordion-header.directive';\nimport { AccordionContentDirective } from './accordion-content.directive';\nimport { nameWithText } from '@lifecorner/angular-ui-kit/internal/a11y';\n\n/** Unique id source for header/panel wiring (aria-controls / aria-labelledby). */\nlet accordionUid = 0;\n\n/** Where the disclosure chevron sits relative to the header content. */\nexport type AccordionChevronPosition = 'leading' | 'trailing';\n\n/** Visual variant of `lc-accordion`. */\nexport type AccordionVariant = 'outlined' | 'flat' | 'plain';\n\n/**\n * Accordion component for collapsible content sections.\n *\n * Features:\n * - Expandable/collapsible content panels\n * - Two-way binding for expanded state\n * - Animated expand/collapse transitions\n * - Plain-string `title` **or** a rich projected header (`lcAccordionHeader`)\n * - Eager `<ng-content>` body **or** lazy/destroyable template body\n * (`lcAccordionContent` + `[lazy]` / `[destroyOnClose]`)\n * - Accessible: header is a real `<button>` inside a heading with\n * `aria-expanded` / `aria-controls`, keyboard support and a visible focus\n * ring; the collapsed panel is `inert` (not focusable, hidden from AT)\n *\n * @example Plain (unchanged, fully backward compatible)\n * ```html\n * <lc-accordion title=\"Section Title\" [(expanded)]=\"isOpen\">\n * <p>Collapsible content here</p>\n * </lc-accordion>\n * ```\n *\n * @example Rich header + lazy body\n * ```html\n * <lc-accordion variant=\"flat\" chevronPosition=\"leading\" [lazy]=\"true\">\n * <ng-template lcAccordionHeader>\n * <span class=\"title\">Item label</span>&ngsp;\n * <lc-badge variant=\"success\" size=\"sm\">Done</lc-badge>&ngsp;\n * <span style=\"margin-left: auto;\">12:04</span>\n * </ng-template>\n * <ng-template lcAccordionContent>\n * <expensive-panel />\n * </ng-template>\n * </lc-accordion>\n * ```\n */\n@Component({\n selector: 'lc-accordion',\n standalone: true,\n imports: [IconComponent, NgTemplateOutlet],\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_DOWN])],\n templateUrl: './accordion.component.html',\n styleUrl: './accordion.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AccordionComponent {\n /**\n * Title displayed in the accordion header. Optional: when a\n * `lcAccordionHeader` template is projected it takes precedence, and `title`\n * (if set) starts the header's accessible name when `ariaLabel` is empty.\n * @default ''\n */\n readonly title = input<string>('');\n\n /**\n * Start of the header button's accessible name; falls back to `title`. A\n * plain `title` is appended unless contained (WCAG 2.5.3 Label in Name).\n * With an `lcAccordionHeader` template, the name is this label (or `title`)\n * followed by the template's text, through `aria-labelledby`. Separate the\n * template's parts with whitespace (`&ngsp;`), and set a label only for\n * context that the template doesn't show.\n * @default ''\n */\n readonly ariaLabel = input<string>('');\n\n /** Whether the accordion is expanded (two-way binding) */\n readonly expanded = model<boolean>(false);\n\n /**\n * Visual variant. `'outlined'`: border and surface. `'flat'`: no border or\n * background; header and body keep their inset. `'plain'`: no border,\n * background or inline inset, so the title, chevron and body line up with\n * the content edge of the sheet or card around it; the hover background and\n * focus ring reach 8 px past that edge (`--lc-accordion-header-bleed`), so\n * keep that much room before a clipping edge.\n * @default 'outlined'\n */\n readonly variant = input<AccordionVariant>('outlined');\n\n /** Size of the header */\n readonly size = input<'sm' | 'md' | 'lg'>('md');\n\n /** Whether the accordion is disabled */\n readonly disabled = input<boolean>(false);\n\n /**\n * Heading level (1–6) announced for the header button, so the accordion\n * fits into the surrounding document outline.\n * @default 3\n */\n readonly headingLevel = input<1 | 2 | 3 | 4 | 5 | 6>(3);\n\n /**\n * Where the disclosure chevron sits. `'trailing'` (default) preserves the\n * original layout. `'leading'` puts the chevron first so a right-aligned\n * header element (e.g. a timestamp using `margin-left: auto`) stays pinned to\n * the right edge.\n */\n readonly chevronPosition = input<AccordionChevronPosition>('trailing');\n\n /**\n * When `true`, a `lcAccordionContent` body is not instantiated until the\n * panel is first expanded; once created it is kept in the DOM on collapse.\n * Default `false` = today's behavior (projected immediately). Has no effect\n * on default `<ng-content>` bodies, which Angular always projects eagerly.\n */\n readonly lazy = input<boolean>(false);\n\n /**\n * When `true`, a `lcAccordionContent` body is destroyed on collapse and\n * recreated on the next open. Takes precedence over {@link lazy}.\n */\n readonly destroyOnClose = input<boolean>(false);\n\n /** Rich header template, if projected via `lcAccordionHeader`. */\n readonly headerTemplate = contentChild(AccordionHeaderDirective);\n\n /** Lazy/deferred body template, if projected via `lcAccordionContent`. */\n readonly contentTemplate = contentChild(AccordionContentDirective);\n\n /** Stable ids wiring the header button to its panel for screen readers. */\n protected readonly headerId = `lc-accordion-header-${accordionUid}`;\n protected readonly panelId = `lc-accordion-panel-${accordionUid++}`;\n\n /** Latches to `true` the first time the panel is opened (for lazy bodies). */\n private readonly hasBeenOpened = signal(false);\n\n constructor() {\n // Record the first open so lazy bodies can render (and stay) afterwards.\n effect(() => {\n if (this.expanded()) {\n this.hasBeenOpened.set(true);\n }\n });\n }\n\n /**\n * Label that starts a rich header's name (`ariaLabel`, else `title`); empty\n * without a header template.\n */\n protected readonly richHeaderLabel = computed(() =>\n this.headerTemplate() ? (this.ariaLabel() || this.title()).trim() : '',\n );\n\n /**\n * Accessible label of a plain header button (AS-33, WCAG 2.5.3 Label in\n * Name): the explicit override, else the title, then the visible title\n * unless contained. A rich header has none: it is named by its content.\n */\n protected readonly headerAriaLabel = computed(() =>\n this.headerTemplate() ? null : nameWithText(this.ariaLabel() || this.title(), this.title()) || null,\n );\n\n /** A labelled rich header: its hidden label, then the template's text. */\n protected readonly headerLabelledBy = computed(() =>\n this.richHeaderLabel() ? `${this.headerId}-label ${this.headerId}-content` : null,\n );\n\n /**\n * Whether the `lcAccordionContent` body should currently be in the DOM.\n * - `destroyOnClose`: only while expanded.\n * - `lazy`: from the first open onward.\n * - otherwise: always (eager).\n */\n protected readonly shouldRenderBody = computed(() => {\n if (this.destroyOnClose()) return this.expanded();\n if (this.lazy()) return this.hasBeenOpened();\n return true;\n });\n\n /** Computed CSS classes */\n protected accordionClasses = computed(() => {\n const classes = [\n 'lc-accordion',\n `lc-accordion--${this.variant()}`,\n `lc-accordion--${this.size()}`,\n `lc-accordion--chevron-${this.chevronPosition()}`,\n ];\n if (this.expanded()) classes.push('lc-accordion--expanded');\n if (this.disabled()) classes.push('lc-accordion--disabled');\n return classes.join(' ');\n });\n\n /** Toggle expanded state */\n protected toggle(): void {\n if (!this.disabled()) {\n this.expanded.update((v) => !v);\n }\n }\n\n /** Handle keyboard events for accessibility */\n protected onKeydown(event: KeyboardEvent): void {\n if (this.disabled()) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.toggle();\n }\n }\n}\n","<div [class]=\"accordionClasses()\">\n <!-- The heading wrapper gives the disclosure button a heading level (WAI-ARIA accordion pattern). -->\n <div class=\"lc-accordion__heading\" role=\"heading\" [attr.aria-level]=\"headingLevel()\">\n <button\n class=\"lc-accordion__header\"\n type=\"button\"\n [id]=\"headerId\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-label]=\"headerAriaLabel()\"\n [attr.aria-labelledby]=\"headerLabelledBy()\"\n [attr.aria-disabled]=\"disabled()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (headerTemplate(); as header) {\n <!-- The label starts the name and the template's text follows it, so\n the name contains what is shown (WCAG 2.5.3). -->\n @if (richHeaderLabel()) {\n <span hidden [id]=\"headerId + '-label'\">{{ richHeaderLabel() }},</span>\n }\n <span class=\"lc-accordion__header-content\" [attr.id]=\"richHeaderLabel() ? headerId + '-content' : null\">\n <ng-container *ngTemplateOutlet=\"header.template\"></ng-container>\n </span>\n } @else {\n <span class=\"lc-accordion__title\">{{ title() }}</span>\n }\n <lc-icon\n class=\"lc-accordion__icon\"\n name=\"chevron-down\"\n size=\"sm\"\n [decorative]=\"true\"\n ></lc-icon>\n </button>\n </div>\n\n <!--\n A collapsed panel is `inert`: its eagerly projected body stays in the DOM\n (for the height animation) but is neither focusable nor exposed to AT.\n -->\n <div\n class=\"lc-accordion__panel\"\n [id]=\"panelId\"\n role=\"region\"\n [attr.aria-labelledby]=\"headerLabelledBy() ?? headerId\"\n [attr.aria-hidden]=\"!expanded()\"\n [attr.inert]=\"expanded() ? null : ''\"\n >\n <div class=\"lc-accordion__body\">\n @if (contentTemplate(); as content) {\n @if (shouldRenderBody()) {\n <ng-container *ngTemplateOutlet=\"content.template\"></ng-container>\n }\n } @else {\n <ng-content></ng-content>\n }\n </div>\n </div>\n</div>\n","import {\n Component,\n ChangeDetectionStrategy,\n input,\n contentChildren,\n effect,\n untracked,\n} from '@angular/core';\nimport { AccordionComponent } from './accordion.component';\n\n@Component({\n selector: 'lc-accordion-group',\n standalone: true,\n template: '<ng-content></ng-content>',\n styleUrl: './accordion-group.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AccordionGroupComponent {\n /** When false (default), only one accordion can be expanded at a time. */\n readonly multi = input<boolean>(false);\n\n readonly accordions = contentChildren(AccordionComponent);\n\n private previousExpanded = new Set<AccordionComponent>();\n\n constructor() {\n effect(() => {\n const accordions = this.accordions();\n const multi = this.multi();\n\n // Read expanded state of every child so the effect re-runs on change\n const currentlyExpanded = accordions.filter((a) => a.expanded());\n\n if (multi) {\n this.previousExpanded = new Set(currentlyExpanded);\n return;\n }\n\n // Find newly expanded accordion\n const newlyExpanded = currentlyExpanded.find(\n (a) => !this.previousExpanded.has(a)\n );\n\n if (newlyExpanded && currentlyExpanded.length > 1) {\n untracked(() => {\n accordions.forEach((a) => {\n if (a !== newlyExpanded && a.expanded()) {\n a.expanded.set(false);\n }\n });\n });\n }\n\n this.previousExpanded = new Set(\n accordions.filter((a) => a.expanded())\n );\n });\n }\n\n /** Collapse all accordions. */\n collapseAll(): void {\n this.accordions().forEach((a) => a.expanded.set(false));\n }\n\n /** Expand all accordions (only meaningful when multi=true). */\n expandAll(): void {\n this.accordions().forEach((a) => {\n if (!a.disabled()) {\n a.expanded.set(true);\n }\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-accordion.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/accordion/accordion-header.directive.ts","../../../../libs/angular-ui-kit/src/lib/accordion/accordion-content.directive.ts","../../../../libs/angular-ui-kit/src/lib/accordion/accordion.component.ts","../../../../libs/angular-ui-kit/src/lib/accordion/accordion.component.html","../../../../libs/angular-ui-kit/src/lib/accordion/accordion-group.component.ts"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\n\n/**\n * Marks an `<ng-template>` as the rich header content for an `<lc-accordion>`.\n *\n * When present, the projected template is rendered inside the header button\n * instead of the plain `title` string. The accordion still owns the disclosure\n * chevron, click/keyboard handling and focus ring — the consumer only supplies\n * the (non-interactive) inner content.\n *\n * A11y constraint: the header is itself a `<button>`, so the template must not\n * contain nested interactive elements (no button/link/input). Text, badges and\n * other non-interactive nodes only.\n *\n * Name (WCAG 2.5.3 Label in Name): the header is named by the template's\n * text; the accordion's `ariaLabel` (or `title`), if set, comes first through\n * `aria-labelledby`. Separate the template's parts with whitespace\n * (`&ngsp;`), so they read as words (\"Item label Done 12:04\"), and set a\n * label only for context that the template doesn't show.\n *\n * @example\n * ```html\n * <lc-accordion variant=\"flat\" chevronPosition=\"leading\">\n * <ng-template lcAccordionHeader>\n * <span class=\"title\">Item label</span>&ngsp;\n * <lc-badge variant=\"success\" size=\"sm\">Done</lc-badge>&ngsp;\n * <span style=\"margin-left: auto;\">12:04</span>\n * </ng-template>\n * <div>Body…</div>\n * </lc-accordion>\n * ```\n */\n@Directive({\n selector: '[lcAccordionHeader]',\n standalone: true,\n})\nexport class AccordionHeaderDirective {\n public readonly template = inject(TemplateRef<unknown>);\n}\n","import { Directive, TemplateRef, inject } from '@angular/core';\n\n/**\n * Marks an `<ng-template>` as the (optionally lazy) body content for an\n * `<lc-accordion>`.\n *\n * Unlike default `<ng-content>` projection — which Angular always instantiates\n * eagerly — a template referenced through this directive is only stamped out\n * when the accordion decides to render its body. That is what makes\n * `[lazy]=\"true\"` and `[destroyOnClose]=\"true\"` possible: expensive children\n * (HTTP-backed panels, charts, live-polling views) are not created until the\n * panel is first opened.\n *\n * @example\n * ```html\n * <lc-accordion [lazy]=\"true\">\n * <ng-template lcAccordionContent>\n * <expensive-panel [id]=\"id\" />\n * </ng-template>\n * </lc-accordion>\n * ```\n */\n@Directive({\n selector: '[lcAccordionContent]',\n standalone: true,\n})\nexport class AccordionContentDirective {\n public readonly template = inject(TemplateRef<unknown>);\n}\n","import {\n Component,\n ChangeDetectionStrategy,\n input,\n model,\n computed,\n signal,\n contentChild,\n effect,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHEVRON_DOWN } from '@lifecorner/angular-ui-kit/icons';\nimport { AccordionHeaderDirective } from './accordion-header.directive';\nimport { AccordionContentDirective } from './accordion-content.directive';\nimport { nameWithText } from '@lifecorner/angular-ui-kit/internal/a11y';\n\n/** Unique id source for header/panel wiring (aria-controls / aria-labelledby). */\nlet accordionUid = 0;\n\n/** Where the disclosure chevron sits relative to the header content. */\nexport type AccordionChevronPosition = 'leading' | 'trailing';\n\n/** Visual variant of `lc-accordion`. */\nexport type AccordionVariant = 'outlined' | 'flat' | 'plain';\n\n/**\n * Accordion component for collapsible content sections.\n *\n * Features:\n * - Expandable/collapsible content panels\n * - Two-way binding for expanded state\n * - Animated expand/collapse transitions\n * - Plain-string `title` **or** a rich projected header (`lcAccordionHeader`)\n * - Eager `<ng-content>` body **or** lazy/destroyable template body\n * (`lcAccordionContent` + `[lazy]` / `[destroyOnClose]`)\n * - Accessible: header is a real `<button>` inside a heading with\n * `aria-expanded` / `aria-controls`, keyboard support and a visible focus\n * ring; the collapsed panel is `inert` (not focusable, hidden from AT)\n *\n * @example Plain (unchanged, fully backward compatible)\n * ```html\n * <lc-accordion title=\"Section Title\" [(expanded)]=\"isOpen\">\n * <p>Collapsible content here</p>\n * </lc-accordion>\n * ```\n *\n * @example Rich header + lazy body\n * ```html\n * <lc-accordion variant=\"flat\" chevronPosition=\"leading\" [lazy]=\"true\">\n * <ng-template lcAccordionHeader>\n * <span class=\"title\">Item label</span>&ngsp;\n * <lc-badge variant=\"success\" size=\"sm\">Done</lc-badge>&ngsp;\n * <span style=\"margin-left: auto;\">12:04</span>\n * </ng-template>\n * <ng-template lcAccordionContent>\n * <expensive-panel />\n * </ng-template>\n * </lc-accordion>\n * ```\n */\n@Component({\n selector: 'lc-accordion',\n standalone: true,\n imports: [IconComponent, NgTemplateOutlet],\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_DOWN])],\n templateUrl: './accordion.component.html',\n styleUrl: './accordion.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AccordionComponent {\n /**\n * Title displayed in the accordion header. Optional: when a\n * `lcAccordionHeader` template is projected it takes precedence, and `title`\n * (if set) starts the header's accessible name when `ariaLabel` is empty.\n * @default ''\n */\n readonly title = input<string>('');\n\n /**\n * Start of the header button's accessible name; falls back to `title`. A\n * plain `title` is appended unless contained (WCAG 2.5.3 Label in Name).\n * With an `lcAccordionHeader` template, the name is this label (or `title`)\n * followed by the template's text, through `aria-labelledby`. Separate the\n * template's parts with whitespace (`&ngsp;`), and set a label only for\n * context that the template doesn't show.\n * @default ''\n */\n readonly ariaLabel = input<string>('');\n\n /** Whether the accordion is expanded (two-way binding) */\n readonly expanded = model<boolean>(false);\n\n /**\n * Visual variant. `'outlined'`: border and surface. `'flat'`: no border or\n * background; header and body keep their inset. `'plain'`: no border,\n * background or inline inset, so the title, chevron and body line up with\n * the content edge of the sheet or card around it; the hover background and\n * focus ring reach 8 px past that edge (`--lc-accordion-header-bleed`), so\n * keep that much room before a clipping or scrolling edge (`overflow: hidden`\n * or `overflow-x: auto`). The hook takes a length; `0px` puts them on the\n * edge.\n * @default 'outlined'\n */\n readonly variant = input<AccordionVariant>('outlined');\n\n /** Size of the header */\n readonly size = input<'sm' | 'md' | 'lg'>('md');\n\n /** Whether the accordion is disabled */\n readonly disabled = input<boolean>(false);\n\n /**\n * Heading level (1–6) announced for the header button, so the accordion\n * fits into the surrounding document outline.\n * @default 3\n */\n readonly headingLevel = input<1 | 2 | 3 | 4 | 5 | 6>(3);\n\n /**\n * Where the disclosure chevron sits. `'trailing'` (default) preserves the\n * original layout. `'leading'` puts the chevron first so a right-aligned\n * header element (e.g. a timestamp using `margin-left: auto`) stays pinned to\n * the right edge.\n */\n readonly chevronPosition = input<AccordionChevronPosition>('trailing');\n\n /**\n * When `true`, a `lcAccordionContent` body is not instantiated until the\n * panel is first expanded; once created it is kept in the DOM on collapse.\n * Default `false` = today's behavior (projected immediately). Has no effect\n * on default `<ng-content>` bodies, which Angular always projects eagerly.\n */\n readonly lazy = input<boolean>(false);\n\n /**\n * When `true`, a `lcAccordionContent` body is destroyed on collapse and\n * recreated on the next open. Takes precedence over {@link lazy}.\n */\n readonly destroyOnClose = input<boolean>(false);\n\n /** Rich header template, if projected via `lcAccordionHeader`. */\n readonly headerTemplate = contentChild(AccordionHeaderDirective);\n\n /** Lazy/deferred body template, if projected via `lcAccordionContent`. */\n readonly contentTemplate = contentChild(AccordionContentDirective);\n\n /** Stable ids wiring the header button to its panel for screen readers. */\n protected readonly headerId = `lc-accordion-header-${accordionUid}`;\n protected readonly panelId = `lc-accordion-panel-${accordionUid++}`;\n\n /** Latches to `true` the first time the panel is opened (for lazy bodies). */\n private readonly hasBeenOpened = signal(false);\n\n constructor() {\n // Record the first open so lazy bodies can render (and stay) afterwards.\n effect(() => {\n if (this.expanded()) {\n this.hasBeenOpened.set(true);\n }\n });\n }\n\n /**\n * Label that starts a rich header's name (`ariaLabel`, else `title`); empty\n * without a header template.\n */\n protected readonly richHeaderLabel = computed(() =>\n this.headerTemplate() ? (this.ariaLabel() || this.title()).trim() : '',\n );\n\n /**\n * Accessible label of a plain header button (AS-33, WCAG 2.5.3 Label in\n * Name): the explicit override, else the title, then the visible title\n * unless contained. A rich header has none: it is named by its content.\n */\n protected readonly headerAriaLabel = computed(() =>\n this.headerTemplate() ? null : nameWithText(this.ariaLabel() || this.title(), this.title()) || null,\n );\n\n /** A labelled rich header: its hidden label, then the template's text. */\n protected readonly headerLabelledBy = computed(() =>\n this.richHeaderLabel() ? `${this.headerId}-label ${this.headerId}-content` : null,\n );\n\n /**\n * Whether the `lcAccordionContent` body should currently be in the DOM.\n * - `destroyOnClose`: only while expanded.\n * - `lazy`: from the first open onward.\n * - otherwise: always (eager).\n */\n protected readonly shouldRenderBody = computed(() => {\n if (this.destroyOnClose()) return this.expanded();\n if (this.lazy()) return this.hasBeenOpened();\n return true;\n });\n\n /** Computed CSS classes */\n protected accordionClasses = computed(() => {\n const classes = [\n 'lc-accordion',\n `lc-accordion--${this.variant()}`,\n `lc-accordion--${this.size()}`,\n `lc-accordion--chevron-${this.chevronPosition()}`,\n ];\n if (this.expanded()) classes.push('lc-accordion--expanded');\n if (this.disabled()) classes.push('lc-accordion--disabled');\n return classes.join(' ');\n });\n\n /** Toggle expanded state */\n protected toggle(): void {\n if (!this.disabled()) {\n this.expanded.update((v) => !v);\n }\n }\n\n /** Handle keyboard events for accessibility */\n protected onKeydown(event: KeyboardEvent): void {\n if (this.disabled()) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.toggle();\n }\n }\n}\n","<div [class]=\"accordionClasses()\">\n <!-- The heading wrapper gives the disclosure button a heading level (WAI-ARIA accordion pattern). -->\n <div class=\"lc-accordion__heading\" role=\"heading\" [attr.aria-level]=\"headingLevel()\">\n <button\n class=\"lc-accordion__header\"\n type=\"button\"\n [id]=\"headerId\"\n [attr.aria-expanded]=\"expanded()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-label]=\"headerAriaLabel()\"\n [attr.aria-labelledby]=\"headerLabelledBy()\"\n [attr.aria-disabled]=\"disabled()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\"\n (keydown)=\"onKeydown($event)\"\n >\n @if (headerTemplate(); as header) {\n <!-- The label starts the name and the template's text follows it, so\n the name contains what is shown (WCAG 2.5.3). -->\n @if (richHeaderLabel()) {\n <span hidden [id]=\"headerId + '-label'\">{{ richHeaderLabel() }},</span>\n }\n <span class=\"lc-accordion__header-content\" [attr.id]=\"richHeaderLabel() ? headerId + '-content' : null\">\n <ng-container *ngTemplateOutlet=\"header.template\"></ng-container>\n </span>\n } @else {\n <span class=\"lc-accordion__title\">{{ title() }}</span>\n }\n <lc-icon\n class=\"lc-accordion__icon\"\n name=\"chevron-down\"\n size=\"sm\"\n [decorative]=\"true\"\n ></lc-icon>\n </button>\n </div>\n\n <!--\n A collapsed panel is `inert`: its eagerly projected body stays in the DOM\n (for the height animation) but is neither focusable nor exposed to AT.\n -->\n <div\n class=\"lc-accordion__panel\"\n [id]=\"panelId\"\n role=\"region\"\n [attr.aria-labelledby]=\"headerLabelledBy() ?? headerId\"\n [attr.aria-hidden]=\"!expanded()\"\n [attr.inert]=\"expanded() ? null : ''\"\n >\n <div class=\"lc-accordion__body\">\n @if (contentTemplate(); as content) {\n @if (shouldRenderBody()) {\n <ng-container *ngTemplateOutlet=\"content.template\"></ng-container>\n }\n } @else {\n <ng-content></ng-content>\n }\n </div>\n </div>\n</div>\n","import {\n Component,\n ChangeDetectionStrategy,\n input,\n contentChildren,\n effect,\n untracked,\n} from '@angular/core';\nimport { AccordionComponent } from './accordion.component';\n\n@Component({\n selector: 'lc-accordion-group',\n standalone: true,\n template: '<ng-content></ng-content>',\n styleUrl: './accordion-group.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AccordionGroupComponent {\n /** When false (default), only one accordion can be expanded at a time. */\n readonly multi = input<boolean>(false);\n\n readonly accordions = contentChildren(AccordionComponent);\n\n private previousExpanded = new Set<AccordionComponent>();\n\n constructor() {\n effect(() => {\n const accordions = this.accordions();\n const multi = this.multi();\n\n // Read expanded state of every child so the effect re-runs on change\n const currentlyExpanded = accordions.filter((a) => a.expanded());\n\n if (multi) {\n this.previousExpanded = new Set(currentlyExpanded);\n return;\n }\n\n // Find newly expanded accordion\n const newlyExpanded = currentlyExpanded.find(\n (a) => !this.previousExpanded.has(a)\n );\n\n if (newlyExpanded && currentlyExpanded.length > 1) {\n untracked(() => {\n accordions.forEach((a) => {\n if (a !== newlyExpanded && a.expanded()) {\n a.expanded.set(false);\n }\n });\n });\n }\n\n this.previousExpanded = new Set(\n accordions.filter((a) => a.expanded())\n );\n });\n }\n\n /** Collapse all accordions. */\n collapseAll(): void {\n this.accordions().forEach((a) => a.expanded.set(false));\n }\n\n /** Expand all accordions (only meaningful when multi=true). */\n expandAll(): void {\n this.accordions().forEach((a) => {\n if (!a.disabled()) {\n a.expanded.set(true);\n }\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -427,7 +427,7 @@ var CodeBlockComponent = class CodeBlockComponent {
|
|
|
427
427
|
},
|
|
428
428
|
ngImport: i0,
|
|
429
429
|
template: "<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div\n class=\"code-block__body\"\n [attr.tabindex]=\"wrap() ? null : 0\"\n [attr.role]=\"wrap() ? null : 'region'\"\n [attr.aria-label]=\"wrap() ? null : regionName()\"\n >\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\">@for (segment of line; track $index) {@if (segment.className) {<span [attr.class]=\"segment.className\">{{ segment.text }}</span>}@else{{{ segment.text }}}}</span></span>\n}</code></pre>\n </div>\n</div>\n",
|
|
430
|
-
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:
|
|
430
|
+
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px}.code-block__copy:focus-visible{color:var(--lc-code-block-muted-strong)}.code-block__live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.code-block__body{overflow-x:auto}.code-block__body:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-4px}.code-block__body:focus-visible{border-radius:0 0 calc(var(--border-radius-md) - 1px) calc(var(--border-radius-md) - 1px)}.code-block__body:first-child:focus-visible{border-radius:calc(var(--border-radius-md) - 1px)}@media(forced-colors:active){.code-block__body:focus-visible{outline-color:Highlight}}.code-block__pre{margin:0;padding:1rem;background:transparent;color:inherit;border-radius:0;overflow:visible}.code-block__code{display:block}.code-block__line{display:flex}.code-block__line-number{display:inline-block;min-width:2.5rem;padding-right:1rem;text-align:right;color:var(--lc-code-block-muted);-webkit-user-select:none;user-select:none;flex-shrink:0}.code-block__line-content{flex:1;white-space:pre}.code-block__line-content ::ng-deep .token-keyword{color:#c678dd}.code-block__line-content ::ng-deep .token-string{color:#98c379}.code-block__line-content ::ng-deep .token-number{color:#d19a66}.code-block__line-content ::ng-deep .token-comment{color:var(--lc-code-block-muted);font-style:italic}.code-block__line-content ::ng-deep .token-type{color:#e5c07b}.code-block__line-content ::ng-deep .token-constant{color:#d19a66}.code-block__line-content ::ng-deep .token-decorator{color:#61afef}.code-block__line-content ::ng-deep .token-tag{color:#e06c75}.code-block__line-content ::ng-deep .token-attr{color:#d19a66}.code-block__line-content ::ng-deep .token-selector{color:#e06c75}.code-block__line-content ::ng-deep .token-property{color:#61afef}.code-block__line-content ::ng-deep .token-unit{color:#d19a66}.code-block__line-content ::ng-deep .token-variable{color:#e06c75}.code-block__line-content ::ng-deep .token-builtin{color:#61afef}.code-block__line-content ::ng-deep .token-flag{color:#56b6c2}.code-block--wrap .code-block__line-content{white-space:pre-wrap;overflow-wrap:anywhere;min-width:0}@media(forced-colors:active){.code-block__copy:focus-visible{outline-color:Highlight}}\n"],
|
|
431
431
|
dependencies: [{
|
|
432
432
|
kind: "component",
|
|
433
433
|
type: IconComponent,
|
|
@@ -460,7 +460,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
460
460
|
viewProviders: [ɵprovideKitIcons([ICON_CHECK, ICON_CLIPBOARD])],
|
|
461
461
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
462
462
|
template: "<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div\n class=\"code-block__body\"\n [attr.tabindex]=\"wrap() ? null : 0\"\n [attr.role]=\"wrap() ? null : 'region'\"\n [attr.aria-label]=\"wrap() ? null : regionName()\"\n >\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\">@for (segment of line; track $index) {@if (segment.className) {<span [attr.class]=\"segment.className\">{{ segment.text }}</span>}@else{{{ segment.text }}}}</span></span>\n}</code></pre>\n </div>\n</div>\n",
|
|
463
|
-
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:
|
|
463
|
+
styles: [".code-block{--lc-code-block-bg: #0c1722;--lc-code-block-ink: #eef4f6;--lc-code-block-muted: #93a4ad;--lc-code-block-muted-strong: #c4d2d9;--lc-code-block-border: #24343f;position:relative;border:1px solid var(--lc-code-block-border);border-radius:var(--border-radius-md);overflow:hidden;font-family:var(--typography-font-family-mono, \"SF Mono\", \"Fira Code\", \"Fira Mono\", monospace);font-size:var(--typography-font-size-sm, .875rem);line-height:1.1;background-color:var(--lc-code-block-bg);color:var(--lc-code-block-ink)}.code-block__header{display:flex;justify-content:space-between;align-items:center;min-height:2.75rem;padding:0 .25rem 0 1rem;background-color:#00000040;border-bottom:1px solid var(--lc-code-block-border)}.code-block__language{font-size:var(--typography-font-size-xs, .75rem);color:var(--lc-code-block-muted);text-transform:lowercase;-webkit-user-select:none;user-select:none}.code-block__copy{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;min-height:2.75rem;min-width:2.75rem;padding:0 .75rem;border:none;border-radius:var(--border-radius-sm);background:transparent;color:var(--lc-code-block-muted);font-size:var(--typography-font-size-xs, .75rem);font-family:inherit;cursor:pointer;transition:color .15s ease,background-color .15s ease}.code-block__copy:hover{color:var(--lc-code-block-muted-strong);background-color:#ffffff0f}.code-block__copy:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-2px}.code-block__copy:focus-visible{color:var(--lc-code-block-muted-strong)}.code-block__live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.code-block__body{overflow-x:auto}.code-block__body:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:-4px}.code-block__body:focus-visible{border-radius:0 0 calc(var(--border-radius-md) - 1px) calc(var(--border-radius-md) - 1px)}.code-block__body:first-child:focus-visible{border-radius:calc(var(--border-radius-md) - 1px)}@media(forced-colors:active){.code-block__body:focus-visible{outline-color:Highlight}}.code-block__pre{margin:0;padding:1rem;background:transparent;color:inherit;border-radius:0;overflow:visible}.code-block__code{display:block}.code-block__line{display:flex}.code-block__line-number{display:inline-block;min-width:2.5rem;padding-right:1rem;text-align:right;color:var(--lc-code-block-muted);-webkit-user-select:none;user-select:none;flex-shrink:0}.code-block__line-content{flex:1;white-space:pre}.code-block__line-content ::ng-deep .token-keyword{color:#c678dd}.code-block__line-content ::ng-deep .token-string{color:#98c379}.code-block__line-content ::ng-deep .token-number{color:#d19a66}.code-block__line-content ::ng-deep .token-comment{color:var(--lc-code-block-muted);font-style:italic}.code-block__line-content ::ng-deep .token-type{color:#e5c07b}.code-block__line-content ::ng-deep .token-constant{color:#d19a66}.code-block__line-content ::ng-deep .token-decorator{color:#61afef}.code-block__line-content ::ng-deep .token-tag{color:#e06c75}.code-block__line-content ::ng-deep .token-attr{color:#d19a66}.code-block__line-content ::ng-deep .token-selector{color:#e06c75}.code-block__line-content ::ng-deep .token-property{color:#61afef}.code-block__line-content ::ng-deep .token-unit{color:#d19a66}.code-block__line-content ::ng-deep .token-variable{color:#e06c75}.code-block__line-content ::ng-deep .token-builtin{color:#61afef}.code-block__line-content ::ng-deep .token-flag{color:#56b6c2}.code-block--wrap .code-block__line-content{white-space:pre-wrap;overflow-wrap:anywhere;min-width:0}@media(forced-colors:active){.code-block__copy:focus-visible{outline-color:Highlight}}\n"]
|
|
464
464
|
}]
|
|
465
465
|
}],
|
|
466
466
|
propDecorators: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-code-block.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.ts","../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n signal,\n} from '@angular/core';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHECK, ICON_CLIPBOARD } from '@lifecorner/angular-ui-kit/icons';\n\nexport type CodeBlockLanguage =\n | 'typescript'\n | 'javascript'\n | 'html'\n | 'css'\n | 'scss'\n | 'json'\n | 'bash'\n | 'python'\n | 'java'\n | 'text';\n\ninterface TokenRule {\n pattern: RegExp;\n className: string;\n}\n\nconst SHARED_RULES: TokenRule[] = [\n // Strings (double/single/backtick)\n { pattern: /`(?:[^`\\\\]|\\\\.)*`/g, className: 'token-string' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"/g, className: 'token-string' },\n { pattern: /'(?:[^'\\\\]|\\\\.)*'/g, className: 'token-string' },\n // Numbers\n { pattern: /\\b\\d+(?:\\.\\d+)?\\b/g, className: 'token-number' },\n];\n\nconst LANGUAGE_RULES: Record<string, TokenRule[]> = {\n typescript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|interface|type|enum|extends|implements|new|this|super|async|await|yield|of|in|as|is|readonly|public|private|protected|static|abstract|override|get|set|constructor|declare|namespace|module|require)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:string|number|boolean|void|null|undefined|never|any|unknown|object|symbol|bigint)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n { pattern: /(?<=\\b(?:class|interface|type|enum|extends|implements)\\s+)\\w+/g, className: 'token-type' },\n ],\n javascript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|extends|new|this|super|async|await|yield|of|in|typeof|instanceof|delete|throw|try|catch|finally|switch|case|default|break|continue|do)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n ],\n // The tokenizer reads the raw source (3.6.1): `<` and `>` instead of the\n // `<`/`>` the escaped text had. Up to 3.6.0 an html comment rule ran on\n // that escaped text and never matched; it is gone, so comments stay plain.\n html: [\n ...SHARED_RULES,\n { pattern: /<\\/?[\\w-]+/g, className: 'token-tag' },\n { pattern: /\\/?>/g, className: 'token-tag' },\n { pattern: /\\b[\\w-]+(?==)/g, className: 'token-attr' },\n ],\n css: [\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n { pattern: /\\b(?:px|rem|em|%|vh|vw|s|ms|deg|fr)\\b/g, className: 'token-unit' },\n { pattern: /[\\w-]+(?=\\s*:)/g, className: 'token-property' },\n ],\n scss: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w-]+/g, className: 'token-variable' },\n { pattern: /@(?:use|forward|import|mixin|include|extend|if|else|each|for|while|function|return)\\b/g, className: 'token-keyword' },\n { pattern: /&/g, className: 'token-selector' },\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n ],\n json: [\n ...SHARED_RULES,\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"(?=\\s*:)/g, className: 'token-property' },\n ],\n bash: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w{][\\w}]*/g, className: 'token-variable' },\n { pattern: /\\b(?:if|then|else|elif|fi|for|do|done|while|until|case|esac|function|in|select|time|coproc)\\b/g, className: 'token-keyword' },\n { pattern: /(?:^|\\s)(?:npm|npx|yarn|pnpm|git|cd|ls|mkdir|rm|cp|mv|echo|cat|grep|find|sed|awk|curl|wget|docker|node|python|pip|brew|apt|sudo)\\b/g, className: 'token-builtin' },\n { pattern: /--?[\\w-]+/g, className: 'token-flag' },\n ],\n python: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n { pattern: /\"\"\"[\\s\\S]*?\"\"\"/g, className: 'token-string' },\n { pattern: /'''[\\s\\S]*?'''/g, className: 'token-string' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:def|class|import|from|as|return|if|elif|else|for|while|break|continue|pass|raise|try|except|finally|with|yield|lambda|assert|del|global|nonlocal|async|await|in|not|and|or|is)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:True|False|None)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:str|int|float|bool|list|dict|tuple|set|bytes|type|object|Exception|ValueError|TypeError|KeyError|IndexError|AttributeError|RuntimeError|StopIteration)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:print|len|range|enumerate|zip|map|filter|sorted|reversed|isinstance|issubclass|hasattr|getattr|setattr|super|property|staticmethod|classmethod|open|input)\\b/g, className: 'token-builtin' },\n { pattern: /\\bself\\b/g, className: 'token-variable' },\n ],\n java: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:abstract|assert|break|case|catch|class|continue|default|do|else|enum|extends|final|finally|for|if|implements|import|instanceof|interface|native|new|package|private|protected|public|return|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|volatile|while|var|record|sealed|permits|yield)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:void|int|long|short|byte|float|double|char|boolean|String|Integer|Long|Double|Float|Boolean|Character|Object|Class|List|Map|Set|ArrayList|HashMap|HashSet|Optional|Stream|Collectors)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:System|Math|Arrays|Collections|Objects|Thread|Runnable)\\b/g, className: 'token-builtin' },\n ],\n};\n\n/** A run of source text; `className` is one `token-*` class, or `null` for plain text. */\ninterface CodeSegment {\n readonly text: string;\n readonly className: string | null;\n}\n\n/** One rendered line: its segments in order. */\ntype CodeLine = readonly CodeSegment[];\n\n/**\n * What an empty line renders: U+00A0, the glyph the ` ` of 3.6.0\n * produced, so the line keeps its height and a selection its text.\n */\nconst EMPTY_LINE: CodeLine = [{ text: String.fromCharCode(0xa0), className: null }];\n\n/** Matches of the language's rules on the raw source, sorted, without overlaps. */\nfunction tokenize(code: string, language: string): { start: number; end: number; className: string }[] {\n const rules = LANGUAGE_RULES[language];\n if (!rules) return [];\n\n // Collect all matches with positions\n const tokens: { start: number; end: number; className: string }[] = [];\n\n for (const rule of rules) {\n const regex = new RegExp(rule.pattern.source, rule.pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(code)) !== null) {\n tokens.push({\n start: match.index,\n end: match.index + match[0].length,\n className: rule.className,\n });\n }\n }\n\n // Sort by start position, longer matches first for same position\n tokens.sort((a, b) => a.start - b.start || b.end - a.end);\n\n // Remove overlapping tokens (keep first/longest)\n const filtered: typeof tokens = [];\n let lastEnd = 0;\n for (const token of tokens) {\n if (token.start >= lastEnd) {\n filtered.push(token);\n lastEnd = token.end;\n }\n }\n return filtered;\n}\n\n/**\n * The highlighted source as lines of text segments, rendered by the template\n * as text nodes and `<span class=\"token-…\">` elements: no markup string, so\n * nothing for Trusted Types to block and nothing in the source is parsed.\n *\n * A token that runs across a line break keeps its class on the part before\n * the first break only; the later parts are plain, as the HTML parser closed\n * the open span at each line end up to 3.6.0.\n */\nfunction highlightLines(code: string, language: string): CodeLine[] {\n const lines: CodeSegment[][] = [[]];\n const append = (text: string, className: string | null) => {\n text.split('\\n').forEach((part, i) => {\n if (i > 0) lines.push([]);\n if (!part) return;\n const line = lines[lines.length - 1];\n const cls = i === 0 ? className : null;\n const last = line[line.length - 1];\n if (cls === null && last?.className === null) {\n line[line.length - 1] = { text: last.text + part, className: null };\n } else {\n line.push({ text: part, className: cls });\n }\n });\n };\n\n let cursor = 0;\n for (const token of tokenize(code, language)) {\n append(code.slice(cursor, token.start), null);\n append(code.slice(token.start, token.end), token.className);\n cursor = token.end;\n }\n append(code.slice(cursor), null);\n\n return lines.map(line => (line.length ? line : EMPTY_LINE));\n}\n\n@Component({\n selector: 'lc-code-block',\n standalone: true,\n imports: [IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHECK, ICON_CLIPBOARD])],\n templateUrl: './code-block.component.html',\n styleUrls: ['./code-block.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Code block component for displaying syntax-highlighted source code.\n *\n * Features:\n * - Syntax highlighting for 10+ languages (TypeScript, Python, Java, etc.)\n * - Optional line numbers\n * - Copy-to-clipboard button\n * - Optional header with filename and language label\n * - Dark-mode compatible color scheme\n * - Keyboard: the body is a focusable, named region that scrolls with the\n * arrow keys; `wrap` wraps instead\n *\n * @example\n * ```html\n * <lc-code-block [code]=\"source\" language=\"typescript\" [showLineNumbers]=\"true\" />\n * ```\n */\nexport class CodeBlockComponent {\n /** Code content to display */\n code = input.required<string>();\n\n /** Language label */\n language = input<CodeBlockLanguage>('text');\n\n /** Optional filename to display */\n filename = input<string>();\n\n /** Whether to show line numbers */\n showLineNumbers = input<boolean>(true);\n\n /** Whether to show copy button */\n showCopy = input<boolean>(true);\n\n /** Whether the code block has a header bar */\n showHeader = input<boolean>(true);\n\n /**\n * Accessible name of the scrollable code region (`role=\"region\"`). When it\n * is unset or empty, the `filename` is used, then the `language`. Set a\n * short, localised name that is unique on the page, such as \"Befehl für\n * Claude Code\". Not used when `wrap` is set.\n * @default undefined\n */\n regionLabel = input<string | undefined>(undefined);\n\n /**\n * Wraps long lines (`white-space: pre-wrap`, breaking anywhere if needed)\n * instead of scrolling sideways. A wrapped block doesn't scroll, so its body\n * is neither a tab stop nor a region.\n * @default false\n */\n wrap = input<boolean>(false);\n\n /** Visible label of the copy button. */\n copyLabel = input('Copy');\n\n /** Accessible name of the copy button. */\n copyAriaLabel = input('Copy code');\n\n /** Label of the copy button after copying (also its accessible name). */\n copiedLabel = input('Copied');\n\n /** Announced to screen readers after copying. */\n copiedAnnouncement = input('Copied to clipboard');\n\n protected copied = signal(false);\n\n protected highlightedLines = computed<CodeLine[]>(() =>\n highlightLines(this.code(), this.language())\n );\n\n protected lineNumbers = computed(() => {\n return this.code().split('\\n').map((_, i) => i + 1);\n });\n\n protected headerLabel = computed(() => {\n return this.filename() || this.language();\n });\n\n /** The region's name: `regionLabel`, then `filename`, then `language` (`''` falls through). */\n protected regionName = computed(() => this.regionLabel() || this.headerLabel());\n\n protected codeClasses = computed(() => {\n const classes = ['code-block', `code-block--${this.language()}`];\n if (this.wrap()) classes.push('code-block--wrap');\n return classes.join(' ');\n });\n\n protected async copyToClipboard(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.code());\n this.copied.set(true);\n setTimeout(() => this.copied.set(false), 2000);\n } catch {\n // Fallback: just ignore if clipboard API not available\n }\n }\n}\n","<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div\n class=\"code-block__body\"\n [attr.tabindex]=\"wrap() ? null : 0\"\n [attr.role]=\"wrap() ? null : 'region'\"\n [attr.aria-label]=\"wrap() ? null : regionName()\"\n >\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\">@for (segment of line; track $index) {@if (segment.className) {<span [attr.class]=\"segment.className\">{{ segment.text }}</span>}@else{{{ segment.text }}}}</span></span>\n}</code></pre>\n </div>\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-code-block.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.ts","../../../../libs/angular-ui-kit/src/lib/code-block/code-block.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n signal,\n} from '@angular/core';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHECK, ICON_CLIPBOARD } from '@lifecorner/angular-ui-kit/icons';\n\nexport type CodeBlockLanguage =\n | 'typescript'\n | 'javascript'\n | 'html'\n | 'css'\n | 'scss'\n | 'json'\n | 'bash'\n | 'python'\n | 'java'\n | 'text';\n\ninterface TokenRule {\n pattern: RegExp;\n className: string;\n}\n\nconst SHARED_RULES: TokenRule[] = [\n // Strings (double/single/backtick)\n { pattern: /`(?:[^`\\\\]|\\\\.)*`/g, className: 'token-string' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"/g, className: 'token-string' },\n { pattern: /'(?:[^'\\\\]|\\\\.)*'/g, className: 'token-string' },\n // Numbers\n { pattern: /\\b\\d+(?:\\.\\d+)?\\b/g, className: 'token-number' },\n];\n\nconst LANGUAGE_RULES: Record<string, TokenRule[]> = {\n typescript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|interface|type|enum|extends|implements|new|this|super|async|await|yield|of|in|as|is|readonly|public|private|protected|static|abstract|override|get|set|constructor|declare|namespace|module|require)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:string|number|boolean|void|null|undefined|never|any|unknown|object|symbol|bigint)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n { pattern: /(?<=\\b(?:class|interface|type|enum|extends|implements)\\s+)\\w+/g, className: 'token-type' },\n ],\n javascript: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\b(?:import|export|from|const|let|var|function|return|if|else|for|while|class|extends|new|this|super|async|await|yield|of|in|typeof|instanceof|delete|throw|try|catch|finally|switch|case|default|break|continue|do)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null|undefined|NaN|Infinity)\\b/g, className: 'token-constant' },\n ],\n // The tokenizer reads the raw source (3.6.1): `<` and `>` instead of the\n // `<`/`>` the escaped text had. Up to 3.6.0 an html comment rule ran on\n // that escaped text and never matched; it is gone, so comments stay plain.\n html: [\n ...SHARED_RULES,\n { pattern: /<\\/?[\\w-]+/g, className: 'token-tag' },\n { pattern: /\\/?>/g, className: 'token-tag' },\n { pattern: /\\b[\\w-]+(?==)/g, className: 'token-attr' },\n ],\n css: [\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n { pattern: /\\b(?:px|rem|em|%|vh|vw|s|ms|deg|fr)\\b/g, className: 'token-unit' },\n { pattern: /[\\w-]+(?=\\s*:)/g, className: 'token-property' },\n ],\n scss: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w-]+/g, className: 'token-variable' },\n { pattern: /@(?:use|forward|import|mixin|include|extend|if|else|each|for|while|function|return)\\b/g, className: 'token-keyword' },\n { pattern: /&/g, className: 'token-selector' },\n { pattern: /[.#][\\w-]+/g, className: 'token-selector' },\n ],\n json: [\n ...SHARED_RULES,\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\"(?:[^\"\\\\]|\\\\.)*\"(?=\\s*:)/g, className: 'token-property' },\n ],\n bash: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /\\$[\\w{][\\w}]*/g, className: 'token-variable' },\n { pattern: /\\b(?:if|then|else|elif|fi|for|do|done|while|until|case|esac|function|in|select|time|coproc)\\b/g, className: 'token-keyword' },\n { pattern: /(?:^|\\s)(?:npm|npx|yarn|pnpm|git|cd|ls|mkdir|rm|cp|mv|echo|cat|grep|find|sed|awk|curl|wget|docker|node|python|pip|brew|apt|sudo)\\b/g, className: 'token-builtin' },\n { pattern: /--?[\\w-]+/g, className: 'token-flag' },\n ],\n python: [\n { pattern: /#.*$/gm, className: 'token-comment' },\n { pattern: /\"\"\"[\\s\\S]*?\"\"\"/g, className: 'token-string' },\n { pattern: /'''[\\s\\S]*?'''/g, className: 'token-string' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:def|class|import|from|as|return|if|elif|else|for|while|break|continue|pass|raise|try|except|finally|with|yield|lambda|assert|del|global|nonlocal|async|await|in|not|and|or|is)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:True|False|None)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:str|int|float|bool|list|dict|tuple|set|bytes|type|object|Exception|ValueError|TypeError|KeyError|IndexError|AttributeError|RuntimeError|StopIteration)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:print|len|range|enumerate|zip|map|filter|sorted|reversed|isinstance|issubclass|hasattr|getattr|setattr|super|property|staticmethod|classmethod|open|input)\\b/g, className: 'token-builtin' },\n { pattern: /\\bself\\b/g, className: 'token-variable' },\n ],\n java: [\n { pattern: /\\/\\/.*$/gm, className: 'token-comment' },\n { pattern: /\\/\\*[\\s\\S]*?\\*\\//g, className: 'token-comment' },\n ...SHARED_RULES,\n { pattern: /@\\w+/g, className: 'token-decorator' },\n { pattern: /\\b(?:abstract|assert|break|case|catch|class|continue|default|do|else|enum|extends|final|finally|for|if|implements|import|instanceof|interface|native|new|package|private|protected|public|return|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|volatile|while|var|record|sealed|permits|yield)\\b/g, className: 'token-keyword' },\n { pattern: /\\b(?:true|false|null)\\b/g, className: 'token-constant' },\n { pattern: /\\b(?:void|int|long|short|byte|float|double|char|boolean|String|Integer|Long|Double|Float|Boolean|Character|Object|Class|List|Map|Set|ArrayList|HashMap|HashSet|Optional|Stream|Collectors)\\b/g, className: 'token-type' },\n { pattern: /\\b(?:System|Math|Arrays|Collections|Objects|Thread|Runnable)\\b/g, className: 'token-builtin' },\n ],\n};\n\n/** A run of source text; `className` is one `token-*` class, or `null` for plain text. */\ninterface CodeSegment {\n readonly text: string;\n readonly className: string | null;\n}\n\n/** One rendered line: its segments in order. */\ntype CodeLine = readonly CodeSegment[];\n\n/**\n * What an empty line renders: U+00A0, the glyph the ` ` of 3.6.0\n * produced, so the line keeps its height and a selection its text.\n */\nconst EMPTY_LINE: CodeLine = [{ text: String.fromCharCode(0xa0), className: null }];\n\n/** Matches of the language's rules on the raw source, sorted, without overlaps. */\nfunction tokenize(code: string, language: string): { start: number; end: number; className: string }[] {\n const rules = LANGUAGE_RULES[language];\n if (!rules) return [];\n\n // Collect all matches with positions\n const tokens: { start: number; end: number; className: string }[] = [];\n\n for (const rule of rules) {\n const regex = new RegExp(rule.pattern.source, rule.pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(code)) !== null) {\n tokens.push({\n start: match.index,\n end: match.index + match[0].length,\n className: rule.className,\n });\n }\n }\n\n // Sort by start position, longer matches first for same position\n tokens.sort((a, b) => a.start - b.start || b.end - a.end);\n\n // Remove overlapping tokens (keep first/longest)\n const filtered: typeof tokens = [];\n let lastEnd = 0;\n for (const token of tokens) {\n if (token.start >= lastEnd) {\n filtered.push(token);\n lastEnd = token.end;\n }\n }\n return filtered;\n}\n\n/**\n * The highlighted source as lines of text segments, rendered by the template\n * as text nodes and `<span class=\"token-…\">` elements: no markup string, so\n * nothing for Trusted Types to block and nothing in the source is parsed.\n *\n * A token that runs across a line break keeps its class on the part before\n * the first break only; the later parts are plain, as the HTML parser closed\n * the open span at each line end up to 3.6.0.\n */\nfunction highlightLines(code: string, language: string): CodeLine[] {\n const lines: CodeSegment[][] = [[]];\n const append = (text: string, className: string | null) => {\n text.split('\\n').forEach((part, i) => {\n if (i > 0) lines.push([]);\n if (!part) return;\n const line = lines[lines.length - 1];\n const cls = i === 0 ? className : null;\n const last = line[line.length - 1];\n if (cls === null && last?.className === null) {\n line[line.length - 1] = { text: last.text + part, className: null };\n } else {\n line.push({ text: part, className: cls });\n }\n });\n };\n\n let cursor = 0;\n for (const token of tokenize(code, language)) {\n append(code.slice(cursor, token.start), null);\n append(code.slice(token.start, token.end), token.className);\n cursor = token.end;\n }\n append(code.slice(cursor), null);\n\n return lines.map(line => (line.length ? line : EMPTY_LINE));\n}\n\n@Component({\n selector: 'lc-code-block',\n standalone: true,\n imports: [IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHECK, ICON_CLIPBOARD])],\n templateUrl: './code-block.component.html',\n styleUrls: ['./code-block.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Code block component for displaying syntax-highlighted source code.\n *\n * Features:\n * - Syntax highlighting for 10+ languages (TypeScript, Python, Java, etc.)\n * - Optional line numbers\n * - Copy-to-clipboard button\n * - Optional header with filename and language label\n * - Dark-mode compatible color scheme\n * - Keyboard: the body is a focusable, named region that scrolls with the\n * arrow keys; `wrap` wraps instead\n *\n * @example\n * ```html\n * <lc-code-block [code]=\"source\" language=\"typescript\" [showLineNumbers]=\"true\" />\n * ```\n */\nexport class CodeBlockComponent {\n /** Code content to display */\n code = input.required<string>();\n\n /** Language label */\n language = input<CodeBlockLanguage>('text');\n\n /** Optional filename to display */\n filename = input<string>();\n\n /** Whether to show line numbers */\n showLineNumbers = input<boolean>(true);\n\n /** Whether to show copy button */\n showCopy = input<boolean>(true);\n\n /** Whether the code block has a header bar */\n showHeader = input<boolean>(true);\n\n /**\n * Accessible name of the scrollable code region (`role=\"region\"`). When it\n * is unset or empty, the `filename` is used, then the `language`. Set a\n * short, localised name that is unique on the page, such as \"Befehl für\n * Claude Code\". Not used when `wrap` is set.\n * @default undefined\n */\n regionLabel = input<string | undefined>(undefined);\n\n /**\n * Wraps long lines (`white-space: pre-wrap`, breaking anywhere if needed)\n * instead of scrolling sideways. A wrapped block doesn't scroll, so its body\n * is neither a tab stop nor a region.\n * @default false\n */\n wrap = input<boolean>(false);\n\n /** Visible label of the copy button. */\n copyLabel = input('Copy');\n\n /** Accessible name of the copy button. */\n copyAriaLabel = input('Copy code');\n\n /** Label of the copy button after copying (also its accessible name). */\n copiedLabel = input('Copied');\n\n /** Announced to screen readers after copying. */\n copiedAnnouncement = input('Copied to clipboard');\n\n protected copied = signal(false);\n\n protected highlightedLines = computed<CodeLine[]>(() =>\n highlightLines(this.code(), this.language())\n );\n\n protected lineNumbers = computed(() => {\n return this.code().split('\\n').map((_, i) => i + 1);\n });\n\n protected headerLabel = computed(() => {\n return this.filename() || this.language();\n });\n\n /** The region's name: `regionLabel`, then `filename`, then `language` (`''` falls through). */\n protected regionName = computed(() => this.regionLabel() || this.headerLabel());\n\n protected codeClasses = computed(() => {\n const classes = ['code-block', `code-block--${this.language()}`];\n if (this.wrap()) classes.push('code-block--wrap');\n return classes.join(' ');\n });\n\n protected async copyToClipboard(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.code());\n this.copied.set(true);\n setTimeout(() => this.copied.set(false), 2000);\n } catch {\n // Fallback: just ignore if clipboard API not available\n }\n }\n}\n","<div [class]=\"codeClasses()\">\n @if (showHeader()) {\n <div class=\"code-block__header\">\n <span class=\"code-block__language\">{{ headerLabel() }}</span>\n @if (showCopy()) {\n <button\n type=\"button\"\n class=\"code-block__copy\"\n [attr.aria-label]=\"copied() ? copiedLabel() : copyAriaLabel()\"\n (click)=\"copyToClipboard()\"\n >\n @if (copied()) {\n <lc-icon name=\"check\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copiedLabel() }}</span>\n } @else {\n <lc-icon name=\"clipboard-document\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ copyLabel() }}</span>\n }\n </button>\n <span class=\"code-block__live\" role=\"status\" aria-live=\"polite\">{{ copied() ? copiedAnnouncement() : '' }}</span>\n }\n </div>\n }\n <div\n class=\"code-block__body\"\n [attr.tabindex]=\"wrap() ? null : 0\"\n [attr.role]=\"wrap() ? null : 'region'\"\n [attr.aria-label]=\"wrap() ? null : regionName()\"\n >\n <pre class=\"code-block__pre\"><code class=\"code-block__code\">@for (line of highlightedLines(); track $index; let i = $index) {<span class=\"code-block__line\">@if (showLineNumbers()) {<span class=\"code-block__line-number\">{{ lineNumbers()[i] }}</span>}<span class=\"code-block__line-content\">@for (segment of line; track $index) {@if (segment.className) {<span [attr.class]=\"segment.className\">{{ segment.text }}</span>}@else{{{ segment.text }}}}</span></span>\n}</code></pre>\n </div>\n</div>\n"],"mappings":"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"}
|
|
@@ -408,7 +408,7 @@ var ComboboxComponent = class ComboboxComponent {
|
|
|
408
408
|
}],
|
|
409
409
|
ngImport: i0,
|
|
410
410
|
template: "<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <div #inputWrapper class=\"lc-combobox__input-wrapper\">\n <!-- Selected chips (multiple mode) -->\n @if (multiple()) {\n @for (sel of selectedMultiple(); track sel.value) {\n <lc-chip\n [removable]=\"!isDisabled()\"\n size=\"sm\"\n (remove)=\"removeSelected(sel)\"\n >{{ sel.label }}</lc-chip>\n }\n }\n\n <input\n #inputEl\n type=\"text\"\n class=\"lc-combobox__input\"\n [id]=\"inputId\"\n [placeholder]=\"multiple() && selectedMultiple().length > 0 ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n autocomplete=\"off\"\n (input)=\"onInputChange($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (isLoading() || loading()) {\n <lc-spinner size=\"sm\" class=\"lc-combobox__spinner\" />\n } @else if (!multiple() && selectedSingle()) {\n <button\n type=\"button\"\n class=\"lc-combobox__clear\"\n [disabled]=\"isDisabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onClearClick()\"\n tabindex=\"-1\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <lc-icon name=\"x-mark\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n\n <!-- Dropdown: rendered in the CDK overlay container so overflow-hidden\n ancestors cannot clip it. Focus stays in the input (mousedown is\n prevented on the panel), keyboard nav uses aria-activedescendant. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"inputWrapper\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayMatchWidth]=\"true\"\n (detach)=\"isOpen.set(false)\"\n >\n <div\n #dropdownEl\n class=\"lc-combobox__dropdown\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @for (group of groupedOptions(); track group.label) {\n @if (group.label) {\n <div class=\"lc-combobox__group-header\" role=\"presentation\">{{ group.label }}</div>\n }\n @for (option of group.items; track option.value) {\n @let idx = flatOptions().indexOf(option);\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option\"\n [class.lc-combobox__option--highlighted]=\"idx === highlightedIndex()\"\n [class.lc-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [id]=\"optionId(idx)\"\n [attr.aria-selected]=\"idx === highlightedIndex()\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"!option.disabled && selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(idx)\"\n >\n @if (option.icon) {\n <lc-icon [name]=\"option.icon\" size=\"sm\" class=\"lc-combobox__option-icon\" [decorative]=\"true\" />\n }\n <div class=\"lc-combobox__option-content\">\n <span class=\"lc-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"lc-combobox__option-desc\">{{ option.description }}</span>\n }\n </div>\n </div>\n }\n }\n\n @if (showCreateOption()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option lc-combobox__option--create\"\n [class.lc-combobox__option--highlighted]=\"highlightedIndex() === flatOptions().length\"\n role=\"option\"\n [id]=\"createOptionId\"\n [attr.aria-selected]=\"highlightedIndex() === flatOptions().length\"\n (click)=\"onCreateNew()\"\n (mouseenter)=\"highlightedIndex.set(flatOptions().length)\"\n >\n <lc-icon name=\"plus\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ createOptionLabel() }} \"{{ query() }}\"</span>\n </div>\n }\n\n @if (visibleOptions().length === 0 && !showCreateOption() && !isLoading() && !loading()) {\n <div class=\"lc-combobox__empty\">{{ emptyMessage() }}</div>\n }\n </div>\n </ng-template>\n\n @if (helperText() && !error()) {\n <span class=\"lc-combobox__helper\" [id]=\"inputId + '-helper'\">{{ helperText() }}</span>\n }\n @if (error()) {\n <span class=\"lc-combobox__error\" [id]=\"inputId + '-error'\" role=\"alert\">{{ error() }}</span>\n }\n</div>\n",
|
|
411
|
-
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{
|
|
411
|
+
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline:2px solid var(--color-error-default);outline-offset:0;box-shadow:none}.lc-combobox--disabled .lc-combobox__input-wrapper{opacity:.6;cursor:not-allowed;background-color:var(--color-surface-muted)}.lc-combobox--disabled .lc-combobox__input-wrapper:hover{border-color:var(--color-border)}.lc-combobox__input{flex:1;min-width:80px;border:none;outline:none;background:transparent;color:var(--color-text-primary);font-family:inherit}.lc-combobox__input::placeholder{color:var(--color-text-tertiary)}.lc-combobox__input:disabled{cursor:not-allowed}.lc-combobox--xs .lc-combobox__input{font-size:var(--font-size-xs, .75rem);height:1.5rem}.lc-combobox--sm .lc-combobox__input{font-size:var(--font-size-sm, .875rem);height:1.75rem}.lc-combobox--md .lc-combobox__input{font-size:var(--font-size-base, 1rem);height:2rem}.lc-combobox--lg .lc-combobox__input{font-size:var(--font-size-lg, 1.125rem);height:2.25rem}.lc-combobox__spinner{flex-shrink:0}.lc-combobox__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;cursor:pointer;color:var(--color-text-tertiary);border-radius:var(--border-radius-sm, .25rem);flex-shrink:0}.lc-combobox__clear:hover:not(:disabled){color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-combobox__clear:disabled{cursor:not-allowed}.lc-combobox__dropdown{margin-top:.25rem;max-height:240px;overflow-y:auto;background-color:var(--color-surface-raised);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-md, .375rem);box-shadow:var(--elevation-3)}.lc-combobox__group-header{padding:.375rem .75rem;font-size:var(--font-size-xs, .75rem);font-weight:600;color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:.05em;margin-top:.25rem}.lc-combobox__group-header:first-child{margin-top:0}.lc-combobox__option{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background-color .1s}.lc-combobox__option--highlighted{background-color:var(--color-surface-hover)}.lc-combobox__option--disabled{opacity:.5;cursor:not-allowed}.lc-combobox__option--create{color:var(--color-primary-600);font-weight:500;border-top:1px solid var(--color-divider)}.lc-combobox__option-icon{flex-shrink:0;color:var(--color-text-tertiary)}.lc-combobox__option-content{display:flex;flex-direction:column;min-width:0}.lc-combobox__option-label{font-size:var(--font-size-sm, .875rem);color:var(--color-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__option-desc{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__empty{padding:.75rem;text-align:center;color:var(--color-text-tertiary);font-size:var(--font-size-sm, .875rem)}.lc-combobox__helper{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary)}.lc-combobox__error{font-size:var(--font-size-xs, .75rem);color:var(--color-text-error)}@media(forced-colors:active){.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline-color:Highlight}}\n"],
|
|
412
412
|
dependencies: [
|
|
413
413
|
{
|
|
414
414
|
kind: "ngmodule",
|
|
@@ -523,7 +523,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
523
523
|
multi: true
|
|
524
524
|
}],
|
|
525
525
|
template: "<div [class]=\"containerClasses()\">\n @if (label()) {\n <label class=\"lc-combobox__label\" [for]=\"inputId\">{{ label() }}</label>\n }\n\n <div #inputWrapper class=\"lc-combobox__input-wrapper\">\n <!-- Selected chips (multiple mode) -->\n @if (multiple()) {\n @for (sel of selectedMultiple(); track sel.value) {\n <lc-chip\n [removable]=\"!isDisabled()\"\n size=\"sm\"\n (remove)=\"removeSelected(sel)\"\n >{{ sel.label }}</lc-chip>\n }\n }\n\n <input\n #inputEl\n type=\"text\"\n class=\"lc-combobox__input\"\n [id]=\"inputId\"\n [placeholder]=\"multiple() && selectedMultiple().length > 0 ? '' : placeholder()\"\n [value]=\"query()\"\n [disabled]=\"isDisabled()\"\n role=\"combobox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-invalid]=\"error() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n autocomplete=\"off\"\n (input)=\"onInputChange($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n @if (isLoading() || loading()) {\n <lc-spinner size=\"sm\" class=\"lc-combobox__spinner\" />\n } @else if (!multiple() && selectedSingle()) {\n <button\n type=\"button\"\n class=\"lc-combobox__clear\"\n [disabled]=\"isDisabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"onClearClick()\"\n tabindex=\"-1\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <lc-icon name=\"x-mark\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n\n <!-- Dropdown: rendered in the CDK overlay container so overflow-hidden\n ancestors cannot clip it. Focus stays in the input (mousedown is\n prevented on the panel), keyboard nav uses aria-activedescendant. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"inputWrapper\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayMatchWidth]=\"true\"\n (detach)=\"isOpen.set(false)\"\n >\n <div\n #dropdownEl\n class=\"lc-combobox__dropdown\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n (mousedown)=\"$event.preventDefault()\"\n >\n @for (group of groupedOptions(); track group.label) {\n @if (group.label) {\n <div class=\"lc-combobox__group-header\" role=\"presentation\">{{ group.label }}</div>\n }\n @for (option of group.items; track option.value) {\n @let idx = flatOptions().indexOf(option);\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option\"\n [class.lc-combobox__option--highlighted]=\"idx === highlightedIndex()\"\n [class.lc-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [id]=\"optionId(idx)\"\n [attr.aria-selected]=\"idx === highlightedIndex()\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"!option.disabled && selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(idx)\"\n >\n @if (option.icon) {\n <lc-icon [name]=\"option.icon\" size=\"sm\" class=\"lc-combobox__option-icon\" [decorative]=\"true\" />\n }\n <div class=\"lc-combobox__option-content\">\n <span class=\"lc-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"lc-combobox__option-desc\">{{ option.description }}</span>\n }\n </div>\n </div>\n }\n }\n\n @if (showCreateOption()) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays in the input, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-combobox__option lc-combobox__option--create\"\n [class.lc-combobox__option--highlighted]=\"highlightedIndex() === flatOptions().length\"\n role=\"option\"\n [id]=\"createOptionId\"\n [attr.aria-selected]=\"highlightedIndex() === flatOptions().length\"\n (click)=\"onCreateNew()\"\n (mouseenter)=\"highlightedIndex.set(flatOptions().length)\"\n >\n <lc-icon name=\"plus\" size=\"sm\" [decorative]=\"true\" />\n <span>{{ createOptionLabel() }} \"{{ query() }}\"</span>\n </div>\n }\n\n @if (visibleOptions().length === 0 && !showCreateOption() && !isLoading() && !loading()) {\n <div class=\"lc-combobox__empty\">{{ emptyMessage() }}</div>\n }\n </div>\n </ng-template>\n\n @if (helperText() && !error()) {\n <span class=\"lc-combobox__helper\" [id]=\"inputId + '-helper'\">{{ helperText() }}</span>\n }\n @if (error()) {\n <span class=\"lc-combobox__error\" [id]=\"inputId + '-error'\" role=\"alert\">{{ error() }}</span>\n }\n</div>\n",
|
|
526
|
-
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{
|
|
526
|
+
styles: [".lc-combobox{display:flex;flex-direction:column;gap:.25rem;position:relative;font-family:var(--font-family-sans)}.lc-combobox__label{font-size:var(--font-size-sm, .875rem);font-weight:500;color:var(--color-text-primary);margin-bottom:.125rem}.lc-combobox__input-wrapper{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;border:1px solid var(--color-field-border);border-radius:var(--border-radius-md, .375rem);background-color:var(--color-surface-2);padding:.25rem .5rem;transition:border-color .15s,box-shadow .15s;cursor:text}.lc-combobox__input-wrapper:hover{border-color:var(--color-text-secondary)}.lc-combobox__input-wrapper:focus-within{border-color:var(--color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-primary-500) 20%,transparent)}.lc-combobox--error .lc-combobox__input-wrapper{border-color:var(--color-error-default)}.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline:2px solid var(--color-error-default);outline-offset:0;box-shadow:none}.lc-combobox--disabled .lc-combobox__input-wrapper{opacity:.6;cursor:not-allowed;background-color:var(--color-surface-muted)}.lc-combobox--disabled .lc-combobox__input-wrapper:hover{border-color:var(--color-border)}.lc-combobox__input{flex:1;min-width:80px;border:none;outline:none;background:transparent;color:var(--color-text-primary);font-family:inherit}.lc-combobox__input::placeholder{color:var(--color-text-tertiary)}.lc-combobox__input:disabled{cursor:not-allowed}.lc-combobox--xs .lc-combobox__input{font-size:var(--font-size-xs, .75rem);height:1.5rem}.lc-combobox--sm .lc-combobox__input{font-size:var(--font-size-sm, .875rem);height:1.75rem}.lc-combobox--md .lc-combobox__input{font-size:var(--font-size-base, 1rem);height:2rem}.lc-combobox--lg .lc-combobox__input{font-size:var(--font-size-lg, 1.125rem);height:2.25rem}.lc-combobox__spinner{flex-shrink:0}.lc-combobox__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;cursor:pointer;color:var(--color-text-tertiary);border-radius:var(--border-radius-sm, .25rem);flex-shrink:0}.lc-combobox__clear:hover:not(:disabled){color:var(--color-text-primary);background-color:var(--color-surface-hover)}.lc-combobox__clear:disabled{cursor:not-allowed}.lc-combobox__dropdown{margin-top:.25rem;max-height:240px;overflow-y:auto;background-color:var(--color-surface-raised);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-md, .375rem);box-shadow:var(--elevation-3)}.lc-combobox__group-header{padding:.375rem .75rem;font-size:var(--font-size-xs, .75rem);font-weight:600;color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:.05em;margin-top:.25rem}.lc-combobox__group-header:first-child{margin-top:0}.lc-combobox__option{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;cursor:pointer;transition:background-color .1s}.lc-combobox__option--highlighted{background-color:var(--color-surface-hover)}.lc-combobox__option--disabled{opacity:.5;cursor:not-allowed}.lc-combobox__option--create{color:var(--color-primary-600);font-weight:500;border-top:1px solid var(--color-divider)}.lc-combobox__option-icon{flex-shrink:0;color:var(--color-text-tertiary)}.lc-combobox__option-content{display:flex;flex-direction:column;min-width:0}.lc-combobox__option-label{font-size:var(--font-size-sm, .875rem);color:var(--color-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__option-desc{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-combobox__empty{padding:.75rem;text-align:center;color:var(--color-text-tertiary);font-size:var(--font-size-sm, .875rem)}.lc-combobox__helper{font-size:var(--font-size-xs, .75rem);color:var(--color-text-secondary)}.lc-combobox__error{font-size:var(--font-size-xs, .75rem);color:var(--color-text-error)}@media(forced-colors:active){.lc-combobox--error .lc-combobox__input-wrapper:focus-within{outline-color:Highlight}}\n"]
|
|
527
527
|
}]
|
|
528
528
|
}],
|
|
529
529
|
ctorParameters: () => [],
|