@kouji-ui/components 0.4.3 → 0.5.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.
@@ -1,9 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ChangeDetectionStrategy, ViewEncapsulation, Component, input, booleanAttribute, inject, computed, TemplateRef, model, ViewChild, contentChildren, viewChild, output, EventEmitter, Output, signal, makeEnvironmentProviders, provideEnvironmentInitializer, forwardRef, afterNextRender, ElementRef, DestroyRef, effect, Directive, InjectionToken, ViewContainerRef, EnvironmentInjector, Injector, untracked, contentChild, numberAttribute, PLATFORM_ID } from '@angular/core';
2
+ import { ChangeDetectionStrategy, ViewEncapsulation, Component, input, inject, Injectable, booleanAttribute, computed, TemplateRef, model, ViewChild, contentChildren, ElementRef, PLATFORM_ID, DestroyRef, afterNextRender, effect, signal, Injector, viewChild, untracked, output, EventEmitter, Output, makeEnvironmentProviders, provideEnvironmentInitializer, forwardRef, EnvironmentInjector, Directive, InjectionToken, ViewContainerRef, contentChild, numberAttribute } from '@angular/core';
3
3
  import * as i1 from '@kouji-ui/core';
4
- import { KjAccordion, KjAccordionTrigger, KjAccordionItem, KjAccordionContent, KjAlert, KjAlertIcon, KjAlertTitle, KjAlertDescription, KjAlertActions, KjAlertDismiss, KjIconDirective, KJ_AVATAR_GROUP, KjAvatarImage, KjAvatarFallback, KjAvatar, KjAvatarGroup, KjBadge, KjBreadcrumb, KjBreadcrumbList, KjBreadcrumbItem, KjLink, KjBreadcrumbCurrent, KjBreadcrumbSeparator, KjBreadcrumbEllipsis, KjButton, KjButtonGroup, KjCalendar, KjCalendarHeader, KjCalendarGrid, KjCalendarDay, KjCarousel, KjLiveRegion, KjVisuallyHidden, KjCarouselViewport, KjCarouselSlide, KjCarouselPrevious, KjCarouselNext, KJ_CAROUSEL, KjCarouselIndicator, KjCarouselIndicators, KjCarouselAutoplay, KjCarouselPauseToggle, KjChatLog, KjChat, KjChatAvatar, KjChatHeader, KjChatBubble, KjChatFooter, KjCheckbox, KjColorPicker, KjColorPickerTrigger, KjColorPickerPanel, KjColorPickerArea, KjColorPickerHueSlider, KjColorPickerAlphaSlider, KjColorPickerInput, KjComboboxInput, KjComboboxListbox, KjCombobox, KjComboboxOption, KjConfirmPopup, KjConfirmPopupTrigger, KjPopoverContent, KjConfirmPopupContent, KjConfirmPopupMessage, KjConfirmPopupAction, KjConfirmPopupCancel, KjDatePicker, KjDatePickerTrigger, KjDatePickerCalendar, KjDropdownMenuTrigger, KjDropdownMenuContent, KjDropdownMenuItem, KjDropdownMenuSeparator, KjDropdownMenuLabel, KjDropdownMenuGroup, KJ_SIZE_PRESET, KjSize, KjField, KjFieldLabel, KjFieldHelp, KjFieldError, KjFieldGroup, KjFileUpload, KjFileUploadTrigger, KjFileUploadDropzone, KjFileUploadList, KjFileUploadItem, KjProgressBar, KjProgressBarFill, KjForm, KjFormErrorSummary, KJ_ICON_REGISTRY, KjInput, KjInputGroup, KjInputGroupAddon, KjInputMask, KJ_INPUT_MASK_PRESETS, KjInputOtp, KjInputOtpCell, KjKbd, KJ_KBD_SIZE_PRESET, KjDivider, KJ_VARIANT_PRESET, KjList, KjListRow, KjMenubar, KjMenubarItem, KjNumberInput, KjNumberInputGroup, KjNumberStepper, KJ_OVERLAY_BADGE, KjOverlayBadgeContent, KjOverlayBadge, KjPagination, KjPaginationItem, KjPaginationPrevious, KjPaginationNext, KjPaginationFirst, KjPaginationLast, KjPaginationEllipsis, KjPaginationInfo, KJ_PASSWORD_INPUT, KjPasswordInput, KjPasswordInputScope, KjPasswordToggle, KjPasswordStrength, KjPasswordCapsLockWarning, KjPopoverTrigger, KjPopoverArrow, KjPopoverClose, KjPopoverTitle, KjRadioGroup, KjRadio, KjSelect, KjSelectTrigger, KjSelectContent, KjOption, KjSkeleton, KjSlider, KjSliderTrack, KjSliderRange, KjSliderThumb, KjSpeedDial, KjSpeedDialTrigger, KjSpeedDialActions, KjSpeedDialAction, KjSpinner, KjStepper, KjStep, KjStepLabel, KjStepContent, KjStepperNext, KjStepperPrevious, KjStepperReset, KjToggle, KJ_TABLE, provideKjFilterParams, KjTable, KJ_TABLE_STORAGE, KjTableHeader, KjTableRow, KjTableCell, KjTableKeyboardNav, DRAWER_DATA, KjDrawer, KjDrawerService, KjTabs, KjTabList, KjTab, KjTabPanel, KjTag, KjTagRemove, KjTagList, KjTextarea, KjTimePicker, KjTimePickerHours, KjTimePickerMinutes, KjTimePickerSeconds, KjTimePickerMeridiem, KjToastViewport, KjToast, KjToastClose, KjTooltipTrigger, KjTooltipContent, KjTooltipArrow, KjTooltipGroup, KjCascadeSelect, KjCascadeSelectTrigger, KjCascadeSelectPanel, KjCascadeSelectOption, KjCascadeSelectSubPanel, KjCommandInput, KjCommandList, KjCommandEmpty, KjCommandPalette, injectListItem, KjListItem, KjCommandGroup, KjCommandSeparator, KjTreeSelectNode, KjTreeSelectToggle, KjTreeSelect, KjTreeSelectTrigger, KjTreeSelectContent } from '@kouji-ui/core';
5
- export { KJ_DROPDOWN_MENU, KjBlockquote, KjCode, KjDialog, KjDialogRef, KjDialogService, KjDrawer, KjDrawerRef, KjDrawerService, KjDropdownMenuContent, KjDropdownMenuGroup, KjDropdownMenuItem, KjDropdownMenuLabel, KjDropdownMenuSeparator, KjDropdownMenuTrigger, KjLead, KjMuted, KjPopoverArrow, KjPopoverClose, KjPopoverContent, KjPopoverTitle, KjPopoverTrigger, KjTooltipArrow, KjTooltipContent, KjTooltipGroup, KjTooltipTrigger, KjTruncate } from '@kouji-ui/core';
6
- import { NgTemplateOutlet, isPlatformBrowser } from '@angular/common';
4
+ import { KjAccordion, KjAccordionTrigger, KjAccordionItem, KjAccordionContent, SHEET_DATA, KjSheetRef, KjSheet, KjIconDirective, KjSheetService, KjAlert, KjAlertIcon, KjAlertTitle, KjAlertDescription, KjAlertActions, KjAlertDismiss, KJ_AVATAR_GROUP, KjAvatarImage, KjAvatarFallback, KjAvatar, KjAvatarGroup, KjBadge, KjBreadcrumb, KjBreadcrumbList, KjBreadcrumbItem, KjLink, KjBreadcrumbCurrent, KjBreadcrumbSeparator, KjBreadcrumbEllipsis, KjButton, KjButtonGroup, KjCalendar, KjCalendarHeader, KjCalendarGrid, KjCalendarDay, KjCarousel, KjLiveRegion, KjVisuallyHidden, KjCarouselViewport, KjCarouselSlide, KjCarouselPrevious, KjCarouselNext, KJ_CAROUSEL, KjCarouselIndicator, KjCarouselIndicators, KjCarouselAutoplay, KjCarouselPauseToggle, KjChatLog, KjChat, KjChatAvatar, KjChatHeader, KjChatBubble, KjChatFooter, KjChatAnnouncer, parseSlash, matchSlashCommands, KjCheckbox, KjColorPicker, KjColorPickerTrigger, KjColorPickerPanel, KjColorPickerArea, KjColorPickerHueSlider, KjColorPickerAlphaSlider, KjColorPickerInput, KjComboboxInput, KjComboboxListbox, KjCombobox, KjComboboxOption, KjConfirmPopup, KjConfirmPopupTrigger, KjPopoverContent, KjConfirmPopupContent, KjConfirmPopupMessage, KjConfirmPopupAction, KjConfirmPopupCancel, KjDatePicker, KjDatePickerTrigger, KjDatePickerCalendar, defaultDateRangePresets, KjDateRangePresets, KjDateRangePresetOption, KjLocale, KjDropdownMenuTrigger, KjDropdownMenuContent, KjDropdownMenuItem, KjDropdownMenuSeparator, KjDropdownMenuLabel, KjDropdownMenuGroup, KjSpinner, KjEditorLoader, KjEditor, KJ_SIZE_PRESET, KjSize, KjField, KjFieldLabel, KjFieldHelp, KjFieldError, KjFieldGroup, KjFileUpload, KjFileUploadTrigger, KjFileUploadDropzone, KjFileUploadList, KjFileUploadItem, KjProgressBar, KjProgressBarFill, KjForm, KjFormErrorSummary, KJ_ICON_REGISTRY, KjInput, KjInputGroup, KjInputGroupAddon, KjInputMask, KJ_INPUT_MASK_PRESETS, KjInputOtp, KjInputOtpCell, KjKbd, KJ_KBD_SIZE_PRESET, KjDivider, KJ_VARIANT_PRESET, KjList, KjListRow, KjMenubar, KjMenubarItem, KjNumberInput, KjNumberInputGroup, KjNumberStepper, KJ_OVERLAY_BADGE, KjOverlayBadgeContent, KjOverlayBadge, KjPagination, KjPaginationItem, KjPaginationPrevious, KjPaginationNext, KjPaginationFirst, KjPaginationLast, KjPaginationEllipsis, KjPaginationInfo, KJ_PASSWORD_INPUT, KjPasswordInput, KjPasswordInputScope, KjPasswordToggle, KjPasswordStrength, KjPasswordCapsLockWarning, KjPopoverTrigger, KjPopoverArrow, KjPopoverClose, KjPopoverTitle, KjRadioGroup, KjRadio, injectRteOverlayData, createKjImageNode, KJ_RTE_OVERLAY_DATA, KjRichTextEditor, KjRovingTabindex, KjRovingTabindexItemDirective, KjSelect, KjSelectTrigger, KjSelectContent, KjOption, KjSkeleton, KjSkipLink, KjSlider, KjSliderTrack, KjSliderRange, KjSliderThumb, KjSpeedDial, KjSpeedDialTrigger, KjSpeedDialActions, KjSpeedDialAction, KjStepper, KjStep, KjStepLabel, KjStepContent, KjStepperNext, KjStepperPrevious, KjStepperReset, KjToggle, KJ_TABLE, provideKjFilterParams, KjTable, KJ_TABLE_STORAGE, KjTableHeader, KjTableRow, KjTableCell, KjTableKeyboardNav, DRAWER_DATA, KjDrawer, KjDrawerService, KjTabs, KjTabList, KjTab, KjTabPanel, KjTag, KjTagRemove, KjTagList, KjTextarea, KjTimePicker, KjTimePickerHours, KjTimePickerMinutes, KjTimePickerSeconds, KjTimePickerMeridiem, KjToastViewport, KjToast, KjToastClose, KjTooltipTrigger, KjTooltipContent, KjTooltipArrow, KjTooltipGroup, KjCascadeSelect, KjCascadeSelectTrigger, KjCascadeSelectPanel, KjCascadeSelectOption, KjCascadeSelectSubPanel, KjCommandPalette, KjCommandInput, KjCommandList, KjCommandEmpty, injectListItem, KjListItem, KjCommandGroup, KjCommandSeparator, KjTreeSelectNode, KjTreeSelectToggle, KjTreeSelect, KjTreeSelectTrigger, KjTreeSelectContent } from '@kouji-ui/core';
5
+ export { KJ_DROPDOWN_MENU, KjBlockquote, KjCarousel, KjCarouselSlide, KjCascadeSelectOption, KjChatAnnouncer, KjChatStore, KjCode, KjColorPicker, KjCombobox, KjDatePicker, KjDialog, KjDialogRef, KjDialogService, KjDrawer, KjDrawerRef, KjDrawerService, KjDropdownMenuContent, KjDropdownMenuGroup, KjDropdownMenuItem, KjDropdownMenuLabel, KjDropdownMenuSeparator, KjDropdownMenuTrigger, KjFileUpload, KjInput, KjLead, KjLiveRegion, KjMuted, KjOverlayPanel, KjPopoverArrow, KjPopoverClose, KjPopoverContent, KjPopoverTitle, KjPopoverTrigger, KjRichTextEditor, KjSheet, KjSheetRef, KjSheetService, KjTabPanel, KjTable, KjTooltipArrow, KjTooltipContent, KjTooltipGroup, KjTooltipTrigger, KjTreeSelect, KjTruncate, SHEET_ARIA_LABEL, SHEET_DATA, SHEET_DETENT, SHEET_DISMISSIBLE } from '@kouji-ui/core';
6
+ import { NgTemplateOutlet, isPlatformBrowser, NgComponentOutlet } from '@angular/common';
7
+ import { DomSanitizer } from '@angular/platform-browser';
7
8
  import * as i1$1 from '@angular/forms';
8
9
  import { NG_VALUE_ACCESSOR, FormsModule, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
9
10
  import * as lucideIcons from 'lucide-static';
@@ -180,6 +181,218 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
180
181
  }]
181
182
  }] });
182
183
 
184
+ /**
185
+ * Render body for an action sheet. Rendered programmatically by
186
+ * {@link import('./action-sheet.service').KjActionSheetService} inside the
187
+ * bottom-sheet primitive; reads its config from `SHEET_DATA` and resolves the
188
+ * chosen action's `value` through the {@link KjSheetRef}.
189
+ *
190
+ * The action list is `role="menu"` with `role="menuitem"` rows; each row is a
191
+ * ≥ 44px touch target.
192
+ *
193
+ * @internal
194
+ */
195
+ class KjActionSheet {
196
+ /** Config injected via `SHEET_DATA` by the action-sheet service. */
197
+ config = inject(SHEET_DATA);
198
+ ref = inject(KjSheetRef);
199
+ get cancelLabel() {
200
+ return this.config.cancelLabel === undefined ? 'Cancel' : this.config.cancelLabel;
201
+ }
202
+ /** Resolve the chosen action's value and close. */
203
+ select(action) {
204
+ if (action.disabled)
205
+ return;
206
+ this.ref.close(action.value);
207
+ }
208
+ /** Dismiss with `undefined`. */
209
+ cancel() {
210
+ this.ref.close(undefined);
211
+ }
212
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjActionSheet, deps: [], target: i0.ɵɵFactoryTarget.Component });
213
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjActionSheet, isStandalone: true, selector: "kj-action-sheet", ngImport: i0, template: `
214
+ <kj-sheet class="kj-action-sheet">
215
+ @if (config.title) {
216
+ <h2 class="kj-action-sheet__title">{{ config.title }}</h2>
217
+ }
218
+ @if (config.description) {
219
+ <p class="kj-action-sheet__description">{{ config.description }}</p>
220
+ }
221
+ <div class="kj-action-sheet__list" role="menu" [attr.aria-label]="config.title ?? 'Actions'">
222
+ @for (action of config.actions; track action.value) {
223
+ <button
224
+ type="button"
225
+ role="menuitem"
226
+ class="kj-action-sheet__item"
227
+ [class.is-destructive]="action.role === 'destructive'"
228
+ [disabled]="action.disabled ? true : null"
229
+ (click)="select(action)"
230
+ >
231
+ @if (action.icon) {
232
+ <i class="kj-action-sheet__icon" [kjIcon]="action.icon" aria-hidden="true"></i>
233
+ }
234
+ <span class="kj-action-sheet__label">{{ action.label }}</span>
235
+ </button>
236
+ }
237
+ </div>
238
+ @if (cancelLabel !== null) {
239
+ <button
240
+ type="button"
241
+ class="kj-action-sheet__cancel"
242
+ (click)="cancel()"
243
+ >{{ cancelLabel }}</button>
244
+ }
245
+ </kj-sheet>
246
+ `, isInline: true, dependencies: [{ kind: "component", type: KjSheet, selector: "kj-sheet" }, { kind: "directive", type: KjIconDirective, selector: "span[kjIcon], i[kjIcon]", inputs: ["kjIcon", "kjIconLabel", "kjIconColor", "kjIconSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
247
+ }
248
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjActionSheet, decorators: [{
249
+ type: Component,
250
+ args: [{
251
+ selector: 'kj-action-sheet',
252
+ standalone: true,
253
+ imports: [KjSheet, KjIconDirective],
254
+ changeDetection: ChangeDetectionStrategy.OnPush,
255
+ encapsulation: ViewEncapsulation.None,
256
+ template: `
257
+ <kj-sheet class="kj-action-sheet">
258
+ @if (config.title) {
259
+ <h2 class="kj-action-sheet__title">{{ config.title }}</h2>
260
+ }
261
+ @if (config.description) {
262
+ <p class="kj-action-sheet__description">{{ config.description }}</p>
263
+ }
264
+ <div class="kj-action-sheet__list" role="menu" [attr.aria-label]="config.title ?? 'Actions'">
265
+ @for (action of config.actions; track action.value) {
266
+ <button
267
+ type="button"
268
+ role="menuitem"
269
+ class="kj-action-sheet__item"
270
+ [class.is-destructive]="action.role === 'destructive'"
271
+ [disabled]="action.disabled ? true : null"
272
+ (click)="select(action)"
273
+ >
274
+ @if (action.icon) {
275
+ <i class="kj-action-sheet__icon" [kjIcon]="action.icon" aria-hidden="true"></i>
276
+ }
277
+ <span class="kj-action-sheet__label">{{ action.label }}</span>
278
+ </button>
279
+ }
280
+ </div>
281
+ @if (cancelLabel !== null) {
282
+ <button
283
+ type="button"
284
+ class="kj-action-sheet__cancel"
285
+ (click)="cancel()"
286
+ >{{ cancelLabel }}</button>
287
+ }
288
+ </kj-sheet>
289
+ `,
290
+ }]
291
+ }] });
292
+ /**
293
+ * Service-launched **action sheet** — a data-driven, iOS-style list of actions
294
+ * presented in a bottom sheet. Inject `KjActionSheetService` and call `open()`
295
+ * with a list of actions; selecting one resolves its `value`. Built entirely
296
+ * on the bottom-sheet primitive, so it inherits the same focus trap, scroll
297
+ * lock, drag-to-dismiss, and Escape handling. The wrapper component exists to
298
+ * host this documentation page.
299
+ *
300
+ * @doc
301
+ * @doc-name action-sheet
302
+ * @doc-is-main
303
+ * @doc-example Default
304
+ * A titled action sheet with a destructive action and a cancel row.
305
+ * @doc-file action-sheet.example.ts
306
+ * @doc-example With icons
307
+ * Actions with leading icons; the selected value resolves through the ref.
308
+ * @doc-file action-sheet.icons.example.ts
309
+ *
310
+ * @doc-keyboard
311
+ * Escape — Dismisses the sheet (resolves undefined)
312
+ * Tab / Shift+Tab — Cycles focus across the action rows (focus trap)
313
+ * Enter / Space — Activates the focused action row
314
+ *
315
+ * @doc-aria
316
+ * role — Panel is "dialog"; the action list is "menu" with "menuitem" rows
317
+ * aria-label — The sheet is named by its title (or "Actions" fallback)
318
+ *
319
+ * @doc-touch
320
+ * Every action row and the cancel row is a ≥ 44px touch target (WCAG 2.5.5).
321
+ * The bottom sheet's grab handle dismisses via drag.
322
+ *
323
+ * @doc-a11y
324
+ * Inherits the bottom sheet's a11y contract: focus trapped and restored to
325
+ * the trigger on close, siblings inert while open, only the topmost overlay
326
+ * receives Escape and outside-click. Destructive rows use `--kj-danger-*`
327
+ * tokens which meet AAA contrast in both themes.
328
+ *
329
+ * @doc-related sheet,dialog,dropdown-menu
330
+ *
331
+ * @doc-category Library/Overlay
332
+ */
333
+ class KjActionSheetComponent {
334
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjActionSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
335
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjActionSheetComponent, isStandalone: true, selector: "kj-action-sheet-shell", host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-action-sheet__title{margin:0 0 var(--kj-space-xs);font:600 1.0625rem / 1.3 var(--kj-font-sans);color:var(--kj-fg-default);text-align:center}.kj-action-sheet__description{margin:0 0 var(--kj-space-md);font:.875rem / 1.4 var(--kj-font-sans);color:var(--kj-fg-muted);text-align:center}.kj-action-sheet__list{display:flex;flex-direction:column;gap:var(--kj-space-2xs, .25rem)}.kj-action-sheet__item,.kj-action-sheet__cancel{appearance:none;display:flex;align-items:center;gap:var(--kj-space-sm);width:100%;min-height:44px;padding:var(--kj-space-sm) var(--kj-space-md);border:0;border-radius:var(--kj-radius-md, .5rem);background:var(--kj-bg-subtle, transparent);color:var(--kj-fg-default);font:500 .9375rem / 1.4 var(--kj-font-sans);text-align:left;cursor:pointer}.kj-action-sheet__item:hover:not(:disabled),.kj-action-sheet__cancel:hover{background:var(--kj-bg-muted, var(--kj-border-muted))}.kj-action-sheet__item:focus-visible,.kj-action-sheet__cancel:focus-visible{outline:var(--kj-focus-ring-width, 2px) solid var(--kj-focus-ring-color, var(--kj-primary));outline-offset:2px}.kj-action-sheet__item:disabled{opacity:.5;cursor:not-allowed}.kj-action-sheet__item.is-destructive{color:var(--kj-danger-fg, var(--kj-danger, #d92d20))}.kj-action-sheet__item.is-destructive:hover:not(:disabled){background:var(--kj-danger-bg-subtle, color-mix(in srgb, var(--kj-danger, #d92d20) 12%, transparent))}.kj-action-sheet__icon{flex-shrink:0;width:1.25rem;height:1.25rem}.kj-action-sheet__label{flex:1}.kj-action-sheet__cancel{justify-content:center;margin-top:var(--kj-space-sm);font-weight:600;background:var(--kj-bg-muted, var(--kj-border-muted))}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
336
+ }
337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjActionSheetComponent, decorators: [{
338
+ type: Component,
339
+ args: [{ selector: 'kj-action-sheet-shell', standalone: true, template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-action-sheet__title{margin:0 0 var(--kj-space-xs);font:600 1.0625rem / 1.3 var(--kj-font-sans);color:var(--kj-fg-default);text-align:center}.kj-action-sheet__description{margin:0 0 var(--kj-space-md);font:.875rem / 1.4 var(--kj-font-sans);color:var(--kj-fg-muted);text-align:center}.kj-action-sheet__list{display:flex;flex-direction:column;gap:var(--kj-space-2xs, .25rem)}.kj-action-sheet__item,.kj-action-sheet__cancel{appearance:none;display:flex;align-items:center;gap:var(--kj-space-sm);width:100%;min-height:44px;padding:var(--kj-space-sm) var(--kj-space-md);border:0;border-radius:var(--kj-radius-md, .5rem);background:var(--kj-bg-subtle, transparent);color:var(--kj-fg-default);font:500 .9375rem / 1.4 var(--kj-font-sans);text-align:left;cursor:pointer}.kj-action-sheet__item:hover:not(:disabled),.kj-action-sheet__cancel:hover{background:var(--kj-bg-muted, var(--kj-border-muted))}.kj-action-sheet__item:focus-visible,.kj-action-sheet__cancel:focus-visible{outline:var(--kj-focus-ring-width, 2px) solid var(--kj-focus-ring-color, var(--kj-primary));outline-offset:2px}.kj-action-sheet__item:disabled{opacity:.5;cursor:not-allowed}.kj-action-sheet__item.is-destructive{color:var(--kj-danger-fg, var(--kj-danger, #d92d20))}.kj-action-sheet__item.is-destructive:hover:not(:disabled){background:var(--kj-danger-bg-subtle, color-mix(in srgb, var(--kj-danger, #d92d20) 12%, transparent))}.kj-action-sheet__icon{flex-shrink:0;width:1.25rem;height:1.25rem}.kj-action-sheet__label{flex:1}.kj-action-sheet__cancel{justify-content:center;margin-top:var(--kj-space-sm);font-weight:600;background:var(--kj-bg-muted, var(--kj-border-muted))}}\n"] }]
340
+ }] });
341
+
342
+ /**
343
+ * Reference returned by {@link KjActionSheetService.open}. Resolves the chosen
344
+ * action's `value`, or `undefined` when dismissed (Escape / backdrop / cancel).
345
+ *
346
+ * @doc-category Library/Overlay
347
+ */
348
+ class KjActionSheetRef {
349
+ sheetRef;
350
+ /** Emits the selected value (or `undefined`) once the sheet has closed. */
351
+ afterClosed$;
352
+ /** Promise resolving with the selected value (or `undefined`). */
353
+ result;
354
+ constructor(sheetRef) {
355
+ this.sheetRef = sheetRef;
356
+ this.afterClosed$ = sheetRef.afterClosed$;
357
+ this.result = sheetRef.result;
358
+ }
359
+ /** Dismiss the action sheet programmatically. */
360
+ close(result) {
361
+ this.sheetRef.close(result);
362
+ }
363
+ }
364
+ /**
365
+ * Programmatic service for opening an **action sheet** — a data-driven,
366
+ * iOS-style list of actions presented in a bottom sheet. Built on
367
+ * {@link KjSheetService}; it adds no new overlay surface, only a styled
368
+ * `role="menu"` action list on top of the bottom-sheet primitive.
369
+ *
370
+ * @doc-category Library/Overlay
371
+ */
372
+ class KjActionSheetService {
373
+ sheet = inject(KjSheetService);
374
+ /**
375
+ * Open an action sheet.
376
+ *
377
+ * @param opts - Title, description, actions, and cancel label.
378
+ * @returns A {@link KjActionSheetRef} resolving the selected value.
379
+ */
380
+ open(opts) {
381
+ const sheetRef = this.sheet.open(KjActionSheet, {
382
+ data: opts,
383
+ detent: 'auto',
384
+ ariaLabel: opts.title ?? 'Actions',
385
+ });
386
+ return new KjActionSheetRef(sheetRef);
387
+ }
388
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjActionSheetService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
389
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjActionSheetService, providedIn: 'root' });
390
+ }
391
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjActionSheetService, decorators: [{
392
+ type: Injectable,
393
+ args: [{ providedIn: 'root' }]
394
+ }] });
395
+
183
396
  /**
184
397
  * Styled wrapper around the `KjAlert` directive family. Provides the
185
398
  * persistent in-flow notification surface (severity-aware chrome, severity
@@ -910,7 +1123,7 @@ class KjBreadcrumbComponent {
910
1123
  kjSize = input('md', /* @ts-ignore */
911
1124
  ...(ngDevMode ? [{ debugName: "kjSize" }] : /* istanbul ignore next */ []));
912
1125
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
913
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: KjBreadcrumbComponent, isStandalone: true, selector: "nav[kj-breadcrumb], kj-breadcrumb", inputs: { kjSize: { classPropertyName: "kjSize", publicName: "kjSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, properties: { "attr.data-size": "kjSize()" }, classAttribute: "kj-breadcrumb" }, hostDirectives: [{ directive: i1.KjBreadcrumb, inputs: ["kjAriaLabel", "kjAriaLabel", "kjSeparator", "kjSeparator", "kjMaxItems", "kjMaxItems", "kjOverflow", "kjOverflow"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-breadcrumb{--kj-breadcrumb-gap: var(--kj-space-sm, .5rem);--kj-breadcrumb-separator-content: \"/\";--kj-breadcrumb-overflow-pad: .25rem;--kj-color-breadcrumb-muted: var(--kj-fg-muted);--kj-color-breadcrumb-current: var(--kj-fg-default);display:block;color:var(--kj-color-breadcrumb-muted);font-size:.875rem}.kj-breadcrumb[data-size=sm]{font-size:.8125rem}.kj-breadcrumb[data-size=md]{font-size:.875rem}.kj-breadcrumb[data-size=lg]{font-size:1rem}.kj-breadcrumb-list{display:flex;align-items:center;flex-wrap:nowrap;gap:var(--kj-breadcrumb-gap);margin:0;padding:0;list-style:none;min-width:0}.kj-breadcrumb-list[data-wrap=wrap]{flex-wrap:wrap}.kj-breadcrumb-list[data-wrap=no-wrap],.kj-breadcrumb-list[data-wrap=truncate]{flex-wrap:nowrap}.kj-breadcrumb-item{display:inline-flex;align-items:center;gap:var(--kj-breadcrumb-gap);min-width:0}.kj-breadcrumb-item[data-hidden]{display:none}.kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{content:var(--kj-breadcrumb-separator-content, \"/\");color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none;margin-inline-end:var(--kj-breadcrumb-gap)}[dir=rtl] .kj-breadcrumb[data-mirror-separator] .kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{display:inline-block;transform:scaleX(-1)}.kj-breadcrumb-separator{display:inline-flex;align-items:center;color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none}.kj-breadcrumb-link{text-decoration:none;padding-block:.5rem}.kj-breadcrumb-current{color:var(--kj-color-breadcrumb-current);font-weight:500}.kj-breadcrumb-ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:1.5rem;padding-inline:var(--kj-breadcrumb-overflow-pad);color:var(--kj-color-breadcrumb-muted);background:transparent;border:0;cursor:default;-webkit-user-select:none;user-select:none}.kj-breadcrumb-ellipsis[data-overflow=menu]{cursor:pointer;border-radius:var(--kj-radius-field, .25rem)}.kj-breadcrumb-ellipsis[data-overflow=menu]:hover{background:var(--kj-bg-surface, transparent)}@media print{.kj-breadcrumb-item[data-hidden]{display:revert}.kj-breadcrumb-ellipsis{display:none}}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1126
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: KjBreadcrumbComponent, isStandalone: true, selector: "nav[kj-breadcrumb], kj-breadcrumb", inputs: { kjSize: { classPropertyName: "kjSize", publicName: "kjSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, properties: { "attr.data-size": "kjSize()" }, classAttribute: "kj-breadcrumb" }, hostDirectives: [{ directive: i1.KjBreadcrumb, inputs: ["kjAriaLabel", "kjAriaLabel", "kjSeparator", "kjSeparator", "kjMaxItems", "kjMaxItems", "kjOverflow", "kjOverflow"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-breadcrumb{--kj-breadcrumb-gap: var(--kj-space-sm, .5rem);--kj-breadcrumb-separator-content: \"/\";--kj-breadcrumb-overflow-pad: .25rem;--kj-color-breadcrumb-muted: var(--kj-fg-muted);--kj-color-breadcrumb-current: var(--kj-fg-default);display:block;color:var(--kj-color-breadcrumb-muted);font-size:.875rem}.kj-breadcrumb[data-size=sm]{font-size:.8125rem}.kj-breadcrumb[data-size=md]{font-size:.875rem}.kj-breadcrumb[data-size=lg]{font-size:1rem}.kj-breadcrumb-list{display:flex;align-items:center;flex-wrap:nowrap;gap:var(--kj-breadcrumb-gap);margin:0;padding:0;list-style:none;min-width:0}.kj-breadcrumb-list[data-wrap=wrap]{flex-wrap:wrap}.kj-breadcrumb-list[data-wrap=no-wrap],.kj-breadcrumb-list[data-wrap=truncate]{flex-wrap:nowrap}.kj-breadcrumb-item{display:inline-flex;align-items:center;gap:var(--kj-breadcrumb-gap);min-width:0}.kj-breadcrumb-item[data-hidden]{display:none}.kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{content:var(--kj-breadcrumb-separator-content, \"/\");color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none;margin-inline-end:var(--kj-breadcrumb-gap)}[dir=rtl] .kj-breadcrumb[data-mirror-separator] .kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{display:inline-block;transform:scaleX(-1)}.kj-breadcrumb-separator{display:inline-flex;align-items:center;color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none}.kj-breadcrumb-link{--kj-link-fg: var(--kj-color-breadcrumb-muted);--kj-link-hover-fg: var(--kj-color-breadcrumb-current);color:var(--kj-link-fg);text-decoration:none;padding-block:.5rem;transition:color var(--kj-transition, .15s ease)}.kj-breadcrumb-link:hover{color:var(--kj-link-hover-fg);text-decoration:underline;text-underline-offset:3px}.kj-breadcrumb-link:focus-visible{outline:2px solid var(--kj-fg-primary);outline-offset:2px;border-radius:var(--kj-radius-field, .25rem)}.kj-breadcrumb-current{color:var(--kj-color-breadcrumb-current);font-weight:500}.kj-breadcrumb-ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:1.5rem;padding-inline:var(--kj-breadcrumb-overflow-pad);color:var(--kj-color-breadcrumb-muted);background:transparent;border:0;cursor:default;-webkit-user-select:none;user-select:none}.kj-breadcrumb-ellipsis[data-overflow=menu]{cursor:pointer;border-radius:var(--kj-radius-field, .25rem)}.kj-breadcrumb-ellipsis[data-overflow=menu]:hover{background:var(--kj-bg-surface, transparent)}@media print{.kj-breadcrumb-item[data-hidden]{display:revert}.kj-breadcrumb-ellipsis{display:none}}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
914
1127
  }
915
1128
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjBreadcrumbComponent, decorators: [{
916
1129
  type: Component,
@@ -923,7 +1136,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
923
1136
  'class': 'kj-breadcrumb',
924
1137
  'role': 'navigation',
925
1138
  '[attr.data-size]': 'kjSize()',
926
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-breadcrumb{--kj-breadcrumb-gap: var(--kj-space-sm, .5rem);--kj-breadcrumb-separator-content: \"/\";--kj-breadcrumb-overflow-pad: .25rem;--kj-color-breadcrumb-muted: var(--kj-fg-muted);--kj-color-breadcrumb-current: var(--kj-fg-default);display:block;color:var(--kj-color-breadcrumb-muted);font-size:.875rem}.kj-breadcrumb[data-size=sm]{font-size:.8125rem}.kj-breadcrumb[data-size=md]{font-size:.875rem}.kj-breadcrumb[data-size=lg]{font-size:1rem}.kj-breadcrumb-list{display:flex;align-items:center;flex-wrap:nowrap;gap:var(--kj-breadcrumb-gap);margin:0;padding:0;list-style:none;min-width:0}.kj-breadcrumb-list[data-wrap=wrap]{flex-wrap:wrap}.kj-breadcrumb-list[data-wrap=no-wrap],.kj-breadcrumb-list[data-wrap=truncate]{flex-wrap:nowrap}.kj-breadcrumb-item{display:inline-flex;align-items:center;gap:var(--kj-breadcrumb-gap);min-width:0}.kj-breadcrumb-item[data-hidden]{display:none}.kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{content:var(--kj-breadcrumb-separator-content, \"/\");color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none;margin-inline-end:var(--kj-breadcrumb-gap)}[dir=rtl] .kj-breadcrumb[data-mirror-separator] .kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{display:inline-block;transform:scaleX(-1)}.kj-breadcrumb-separator{display:inline-flex;align-items:center;color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none}.kj-breadcrumb-link{text-decoration:none;padding-block:.5rem}.kj-breadcrumb-current{color:var(--kj-color-breadcrumb-current);font-weight:500}.kj-breadcrumb-ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:1.5rem;padding-inline:var(--kj-breadcrumb-overflow-pad);color:var(--kj-color-breadcrumb-muted);background:transparent;border:0;cursor:default;-webkit-user-select:none;user-select:none}.kj-breadcrumb-ellipsis[data-overflow=menu]{cursor:pointer;border-radius:var(--kj-radius-field, .25rem)}.kj-breadcrumb-ellipsis[data-overflow=menu]:hover{background:var(--kj-bg-surface, transparent)}@media print{.kj-breadcrumb-item[data-hidden]{display:revert}.kj-breadcrumb-ellipsis{display:none}}}\n"] }]
1139
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-breadcrumb{--kj-breadcrumb-gap: var(--kj-space-sm, .5rem);--kj-breadcrumb-separator-content: \"/\";--kj-breadcrumb-overflow-pad: .25rem;--kj-color-breadcrumb-muted: var(--kj-fg-muted);--kj-color-breadcrumb-current: var(--kj-fg-default);display:block;color:var(--kj-color-breadcrumb-muted);font-size:.875rem}.kj-breadcrumb[data-size=sm]{font-size:.8125rem}.kj-breadcrumb[data-size=md]{font-size:.875rem}.kj-breadcrumb[data-size=lg]{font-size:1rem}.kj-breadcrumb-list{display:flex;align-items:center;flex-wrap:nowrap;gap:var(--kj-breadcrumb-gap);margin:0;padding:0;list-style:none;min-width:0}.kj-breadcrumb-list[data-wrap=wrap]{flex-wrap:wrap}.kj-breadcrumb-list[data-wrap=no-wrap],.kj-breadcrumb-list[data-wrap=truncate]{flex-wrap:nowrap}.kj-breadcrumb-item{display:inline-flex;align-items:center;gap:var(--kj-breadcrumb-gap);min-width:0}.kj-breadcrumb-item[data-hidden]{display:none}.kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{content:var(--kj-breadcrumb-separator-content, \"/\");color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none;margin-inline-end:var(--kj-breadcrumb-gap)}[dir=rtl] .kj-breadcrumb[data-mirror-separator] .kj-breadcrumb-list:not([data-explicit-separators])>.kj-breadcrumb-item:not(:first-child):before{display:inline-block;transform:scaleX(-1)}.kj-breadcrumb-separator{display:inline-flex;align-items:center;color:var(--kj-color-breadcrumb-muted);opacity:.65;-webkit-user-select:none;user-select:none}.kj-breadcrumb-link{--kj-link-fg: var(--kj-color-breadcrumb-muted);--kj-link-hover-fg: var(--kj-color-breadcrumb-current);color:var(--kj-link-fg);text-decoration:none;padding-block:.5rem;transition:color var(--kj-transition, .15s ease)}.kj-breadcrumb-link:hover{color:var(--kj-link-hover-fg);text-decoration:underline;text-underline-offset:3px}.kj-breadcrumb-link:focus-visible{outline:2px solid var(--kj-fg-primary);outline-offset:2px;border-radius:var(--kj-radius-field, .25rem)}.kj-breadcrumb-current{color:var(--kj-color-breadcrumb-current);font-weight:500}.kj-breadcrumb-ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:1.5rem;padding-inline:var(--kj-breadcrumb-overflow-pad);color:var(--kj-color-breadcrumb-muted);background:transparent;border:0;cursor:default;-webkit-user-select:none;user-select:none}.kj-breadcrumb-ellipsis[data-overflow=menu]{cursor:pointer;border-radius:var(--kj-radius-field, .25rem)}.kj-breadcrumb-ellipsis[data-overflow=menu]:hover{background:var(--kj-bg-surface, transparent)}@media print{.kj-breadcrumb-item[data-hidden]{display:revert}.kj-breadcrumb-ellipsis{display:none}}}\n"] }]
927
1140
  }], propDecorators: { kjSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSize", required: false }] }] } });
928
1141
  /**
929
1142
  * Wraps `KjBreadcrumbList`. Renders an `<ol>` host inside the breadcrumb
@@ -2285,6 +2498,150 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
2285
2498
  }]
2286
2499
  }], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }] } });
2287
2500
 
2501
+ /** Monotonic id source for wiring `aria-describedby` to the caption span. */
2502
+ let kjChartUid = 0;
2503
+ /**
2504
+ * Reusable charting surface wrapping Apache ECharts.
2505
+ *
2506
+ * SSR-safe: the ECharts instance is created lazily in the browser only, after
2507
+ * the host element has rendered. `option` changes are pushed through
2508
+ * `setOption`, and a `ResizeObserver` keeps the chart sized to its container.
2509
+ *
2510
+ * ECharts paints into an opaque `<canvas>` that assistive technology cannot
2511
+ * read. The host therefore carries `role="img"` plus a required-in-practice
2512
+ * `ariaLabel`, giving screen readers a one-line description. Pass `caption`
2513
+ * for a longer summary — it renders in a visually-hidden `<span>` wired to the
2514
+ * host via `aria-describedby`, so it is announced even though the host is an
2515
+ * image (a leaf) to AT.
2516
+ *
2517
+ * @example
2518
+ * ```html
2519
+ * <kj-chart [option]="chartOption" height="320px" ariaLabel="Revenue by month" />
2520
+ * ```
2521
+ *
2522
+ * @doc-example Default
2523
+ * The default playground — a labelled bar chart with auto-resize.
2524
+ * @doc-file chart.example.ts
2525
+ * @doc-example Usage
2526
+ * A bar chart and a donut, side by side, each with an accessible name and
2527
+ * summary. Use this as the copy-paste starting point.
2528
+ * @doc-file chart.usage.example.ts
2529
+ * @doc-example Donut
2530
+ * A pie series with an inner radius for part-to-whole breakdowns.
2531
+ * @doc-file chart.donut.example.ts
2532
+ *
2533
+ * @doc-aria
2534
+ * role — Always `img`; the canvas is decorative-with-label
2535
+ * aria-label — Bound from `ariaLabel`; the chart's accessible name
2536
+ * aria-describedby — Present only when `caption` is set; points at the sr-only summary
2537
+ *
2538
+ * @doc-a11y
2539
+ * Screen readers get the `ariaLabel` as the accessible name and, when set,
2540
+ * the `caption` as the accessible description. The host is never focusable
2541
+ * and the canvas takes no tab stop, so keyboard users are not trapped. For
2542
+ * dense data, mirror the series in an adjacent `<table>` or export link.
2543
+ *
2544
+ * @doc-related card,table
2545
+ *
2546
+ * @doc-css-var
2547
+ * --kj-chart-height — Container height. Bound from the `height` input.
2548
+ *
2549
+ * @doc-category Library/Data display
2550
+ * @doc
2551
+ * @doc-name chart
2552
+ * @doc-description Accessible Apache ECharts wrapper with reactive options, auto-resize, and SSR-safe lazy init.
2553
+ * @doc-is-main
2554
+ */
2555
+ class KjChartComponent {
2556
+ /** The ECharts option object driving the chart. */
2557
+ option = input(/* @ts-ignore */
2558
+ ...(ngDevMode ? [undefined, { debugName: "option" }] : /* istanbul ignore next */ []));
2559
+ /** Container height — number is treated as pixels. Default `'280px'`. */
2560
+ height = input('280px', /* @ts-ignore */
2561
+ ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
2562
+ /** Optional registered ECharts theme name. */
2563
+ theme = input(/* @ts-ignore */
2564
+ ...(ngDevMode ? [undefined, { debugName: "theme" }] : /* istanbul ignore next */ []));
2565
+ /**
2566
+ * Accessible name for the chart — required in practice. Surfaced via
2567
+ * `role="img"` + `aria-label` so screen readers describe the opaque canvas.
2568
+ * Keep it to a short phrase, e.g. `"Revenue by month"`.
2569
+ */
2570
+ ariaLabel = input('', /* @ts-ignore */
2571
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
2572
+ /**
2573
+ * Optional longer summary read to screen readers. Rendered in a
2574
+ * visually-hidden `<span>` and linked via `aria-describedby`. Use it to
2575
+ * spell out the takeaway a sighted user gets from the shape of the data.
2576
+ */
2577
+ caption = input('', /* @ts-ignore */
2578
+ ...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
2579
+ /** Stable id linking the sr-only caption span to `aria-describedby`. */
2580
+ captionId = `kj-chart-caption-${kjChartUid++}`;
2581
+ host = inject((ElementRef)).nativeElement;
2582
+ platformId = inject(PLATFORM_ID);
2583
+ destroyRef = inject(DestroyRef);
2584
+ chart = null;
2585
+ observer = null;
2586
+ resolvedHeight = () => {
2587
+ const h = this.height();
2588
+ return typeof h === 'number' ? `${h}px` : h;
2589
+ };
2590
+ constructor() {
2591
+ // Create the instance only in the browser, after the host is in the DOM.
2592
+ afterNextRender(() => {
2593
+ if (!isPlatformBrowser(this.platformId))
2594
+ return;
2595
+ void this.init();
2596
+ });
2597
+ // Push option changes to the live instance.
2598
+ effect(() => {
2599
+ const option = this.option();
2600
+ if (this.chart && option) {
2601
+ this.chart.setOption(option, { notMerge: true });
2602
+ }
2603
+ });
2604
+ this.destroyRef.onDestroy(() => this.dispose());
2605
+ }
2606
+ async init() {
2607
+ const echarts = await import('echarts');
2608
+ if (this.chart)
2609
+ return; // guard against double-init / destroyed race
2610
+ this.chart = echarts.init(this.host, this.theme());
2611
+ const option = this.option();
2612
+ if (option)
2613
+ this.chart.setOption(option, { notMerge: true });
2614
+ this.observer = new ResizeObserver(() => this.chart?.resize());
2615
+ this.observer.observe(this.host);
2616
+ }
2617
+ dispose() {
2618
+ this.observer?.disconnect();
2619
+ this.observer = null;
2620
+ this.chart?.dispose();
2621
+ this.chart = null;
2622
+ }
2623
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2624
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjChartComponent, isStandalone: true, selector: "kj-chart", inputs: { option: { classPropertyName: "option", publicName: "option", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "img" }, properties: { "attr.aria-label": "ariaLabel() || null", "attr.aria-describedby": "caption() ? captionId : null", "style.height": "resolvedHeight()" }, classAttribute: "kj-chart" }, ngImport: i0, template: `
2625
+ @if (caption(); as text) {
2626
+ <span [id]="captionId" class="kj-chart__caption">{{ text }}</span>
2627
+ }
2628
+ `, isInline: true, styles: ["@layer kj.component{.kj-chart{display:block;width:100%}.kj-chart__caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2629
+ }
2630
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjChartComponent, decorators: [{
2631
+ type: Component,
2632
+ args: [{ selector: 'kj-chart', standalone: true, template: `
2633
+ @if (caption(); as text) {
2634
+ <span [id]="captionId" class="kj-chart__caption">{{ text }}</span>
2635
+ }
2636
+ `, encapsulation: ViewEncapsulation.None, host: {
2637
+ 'class': 'kj-chart',
2638
+ 'role': 'img',
2639
+ '[attr.aria-label]': 'ariaLabel() || null',
2640
+ '[attr.aria-describedby]': 'caption() ? captionId : null',
2641
+ '[style.height]': 'resolvedHeight()',
2642
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-chart{display:block;width:100%}.kj-chart__caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}}\n"] }]
2643
+ }], ctorParameters: () => [], propDecorators: { option: [{ type: i0.Input, args: [{ isSignal: true, alias: "option", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }] } });
2644
+
2288
2645
  /**
2289
2646
  * Chat log container. Composes `KjChatLog` via `hostDirectives` so the
2290
2647
  * `role="log"` / `aria-live` / `aria-relevant` host bindings land on the
@@ -2548,47 +2905,797 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
2548
2905
  }]
2549
2906
  }] });
2550
2907
 
2551
- let checkboxIdCounter = 0;
2908
+ /** HTML-escape a raw string. */
2909
+ function escapeHtml(s) {
2910
+ return s
2911
+ .replace(/&/g, '&amp;')
2912
+ .replace(/</g, '&lt;')
2913
+ .replace(/>/g, '&gt;')
2914
+ .replace(/"/g, '&quot;')
2915
+ .replace(/'/g, '&#39;');
2916
+ }
2917
+ /** Only allow safe URL schemes for links. */
2918
+ function safeUrl(url) {
2919
+ const trimmed = url.trim();
2920
+ if (/^(https?:\/\/|\/|#|mailto:)/i.test(trimmed))
2921
+ return trimmed;
2922
+ return null;
2923
+ }
2924
+ /** Apply link / bold / italic to a non-code segment. */
2925
+ function formatSegment(seg) {
2926
+ let s = seg.replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, (_m, text, url) => {
2927
+ const href = safeUrl(url);
2928
+ if (!href)
2929
+ return text;
2930
+ return `<a class="kj-md-link" href="${escapeHtml(href)}" rel="noopener noreferrer" target="_blank">${text}</a>`;
2931
+ });
2932
+ s = s.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
2933
+ s = s.replace(/(^|[^*])\*([^*]+)\*/g, '$1<em>$2</em>');
2934
+ return s;
2935
+ }
2552
2936
  /**
2553
- * Styled wrapper around the headless `KjCheckbox` directive.
2937
+ * Render inline markdown on an **already HTML-escaped** string. Splits on
2938
+ * backtick code spans first so their contents are never re-formatted, then
2939
+ * applies link / bold / italic to the remaining prose segments.
2940
+ */
2941
+ function renderInline(escaped) {
2942
+ return escaped
2943
+ .split(/(`[^`]+`)/g)
2944
+ .map((seg) => {
2945
+ if (seg.length >= 2 && seg.startsWith('`') && seg.endsWith('`')) {
2946
+ return `<code class="kj-md-code">${seg.slice(1, -1)}</code>`;
2947
+ }
2948
+ return formatSegment(seg);
2949
+ })
2950
+ .join('');
2951
+ }
2952
+ /** Render a prose block (paragraphs + single-newline `<br>`) to safe HTML. */
2953
+ function renderProse(block) {
2954
+ const paragraphs = block
2955
+ .split(/\n{2,}/)
2956
+ .map((p) => p.trim())
2957
+ .filter(Boolean);
2958
+ return paragraphs
2959
+ .map((p) => {
2960
+ const lines = p.split('\n').map((line) => renderInline(escapeHtml(line)));
2961
+ return `<p>${lines.join('<br>')}</p>`;
2962
+ })
2963
+ .join('');
2964
+ }
2965
+ /**
2966
+ * Parse a lightweight markdown subset into blocks: fenced code blocks
2967
+ * (```lang) become structural `code` blocks; everything else becomes `prose`
2968
+ * blocks with sanitised inline HTML.
2554
2969
  *
2555
- * The host renders a `<label>` wrapping the checkbox box and any projected
2556
- * content (label text). Clicking anywhere on the label checks/unchecks the
2557
- * box. When `disabled` is set, both the box and label text dim via
2558
- * `[data-disabled]` on the host.
2970
+ * Deliberately minimal (no tables / nested lists) and **self-contained** the
2971
+ * repo ships no markdown engine on `main`. Swap in a full parser later without
2972
+ * touching the view.
2973
+ */
2974
+ function renderMarkdown(src) {
2975
+ const blocks = [];
2976
+ const fence = /```([\w-]*)\n?([\s\S]*?)```/g;
2977
+ let last = 0;
2978
+ for (let m = fence.exec(src); m; m = fence.exec(src)) {
2979
+ const before = src.slice(last, m.index);
2980
+ if (before.trim())
2981
+ blocks.push({ kind: 'prose', html: renderProse(before) });
2982
+ blocks.push({ kind: 'code', lang: m[1] || '', code: m[2].replace(/\n$/, '') });
2983
+ last = fence.lastIndex;
2984
+ }
2985
+ const rest = src.slice(last);
2986
+ if (rest.trim())
2987
+ blocks.push({ kind: 'prose', html: renderProse(rest) });
2988
+ return blocks;
2989
+ }
2990
+
2991
+ /** Human-readable accessible name per role. */
2992
+ const ROLE_LABEL = {
2993
+ user: 'You',
2994
+ assistant: 'Assistant',
2995
+ system: 'System',
2996
+ tool: 'Tool',
2997
+ };
2998
+ /**
2999
+ * Renders a single AI-thread message. Reuses the core `KjChat` row directive
3000
+ * for `role="article"` + side semantics, and renders the body per role:
3001
+ * user/assistant get a bubble with **safe markdown** (code blocks carry a copy
3002
+ * button), system gets a centered note, tool gets a tool-call card. Assistant
3003
+ * turns also surface tool-call cards, citations, and a reduced-motion typing
3004
+ * indicator while streaming.
2559
3005
  *
2560
- * @doc-example Default
2561
- * The default checkbox bound to a `signal<boolean>` via `[(checked)]`.
2562
- * @doc-file checkbox.default.example.ts
2563
- * @doc-example Usage
2564
- * A walkthrough of the most common checkbox usages — checked binding,
2565
- * indeterminate parent, size variants, and disabled.
2566
- * @doc-file checkbox.usage.example.ts
2567
- * @doc-example Checked
2568
- * Pre-selected on first render. Two-way bind to persist user changes.
2569
- * @doc-file checkbox.checked.example.ts
2570
- * @doc-example Indeterminate
2571
- * Tri-state "some-of-many" parent for a select-all row.
2572
- * @doc-file checkbox.indeterminate.example.ts
2573
- * @doc-example Disabled
2574
- * `[disabled]="true"` dims the box + label and removes pointer events.
2575
- * @doc-file checkbox.disabled.example.ts
3006
+ * The message is given an `aria-label` (its role name) so AT announces
3007
+ * "Assistant, article" rather than an anonymous region — the visible content is
3008
+ * the message text itself.
3009
+ *
3010
+ * @doc
3011
+ * @doc-name ai-chat
3012
+ */
3013
+ class KjChatMessage {
3014
+ sanitizer = inject(DomSanitizer);
3015
+ /** The message to render. */
3016
+ message = input.required(/* @ts-ignore */
3017
+ ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
3018
+ /** User messages sit on the `end` side; everyone else on `start`. */
3019
+ side = computed(() => (this.message().role === 'user' ? 'end' : 'start'), /* @ts-ignore */
3020
+ ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
3021
+ roleLabel = computed(() => ROLE_LABEL[this.message().role], /* @ts-ignore */
3022
+ ...(ngDevMode ? [{ debugName: "roleLabel" }] : /* istanbul ignore next */ []));
3023
+ avatarGlyph = computed(() => this.roleLabel().charAt(0), /* @ts-ignore */
3024
+ ...(ngDevMode ? [{ debugName: "avatarGlyph" }] : /* istanbul ignore next */ []));
3025
+ showAvatar = computed(() => this.message().role !== 'system', /* @ts-ignore */
3026
+ ...(ngDevMode ? [{ debugName: "showAvatar" }] : /* istanbul ignore next */ []));
3027
+ /** Parsed markdown blocks for the body. */
3028
+ blocks = computed(() => renderMarkdown(this.message().content), /* @ts-ignore */
3029
+ ...(ngDevMode ? [{ debugName: "blocks" }] : /* istanbul ignore next */ []));
3030
+ _copied = signal(null, /* @ts-ignore */
3031
+ ...(ngDevMode ? [{ debugName: "_copied" }] : /* istanbul ignore next */ []));
3032
+ copiedIndex = this._copied.asReadonly();
3033
+ safe(html) {
3034
+ return this.sanitizer.bypassSecurityTrustHtml(html);
3035
+ }
3036
+ async copy(code, index) {
3037
+ try {
3038
+ await navigator.clipboard?.writeText(code);
3039
+ this._copied.set(index);
3040
+ setTimeout(() => this._copied.set(null), 2000);
3041
+ }
3042
+ catch {
3043
+ /* clipboard unavailable — no-op */
3044
+ }
3045
+ }
3046
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjChatMessage, deps: [], target: i0.ɵɵFactoryTarget.Component });
3047
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjChatMessage, isStandalone: true, selector: "kj-chat-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null } }, host: { classAttribute: "kj-chat-msg-host" }, ngImport: i0, template: `
3048
+ <div
3049
+ kjChat
3050
+ class="kj-chat-msg"
3051
+ [kjSide]="side()"
3052
+ [attr.data-role]="message().role"
3053
+ [attr.aria-label]="roleLabel()"
3054
+ >
3055
+ @if (showAvatar()) {
3056
+ <div class="kj-chat-msg__avatar" aria-hidden="true">{{ avatarGlyph() }}</div>
3057
+ }
3058
+
3059
+ <div class="kj-chat-msg__bubble">
3060
+ <!-- Tool-call cards (assistant turns) -->
3061
+ @for (tc of message().toolCalls ?? []; track tc.id) {
3062
+ <div
3063
+ class="kj-chat-tool"
3064
+ [attr.data-status]="tc.status"
3065
+ role="group"
3066
+ [attr.aria-label]="'Tool call: ' + tc.name"
3067
+ >
3068
+ <span class="kj-chat-tool__icon" aria-hidden="true">⚙</span>
3069
+ <span class="kj-chat-tool__name">{{ tc.name }}</span>
3070
+ <span class="kj-chat-tool__status">{{ tc.status }}</span>
3071
+ @if (tc.error) {
3072
+ <span class="kj-chat-tool__error">{{ tc.error }}</span>
3073
+ }
3074
+ </div>
3075
+ }
3076
+
3077
+ <!-- Body -->
3078
+ <div class="kj-chat-msg__body">
3079
+ @for (block of blocks(); track $index) {
3080
+ @if (block.kind === 'code') {
3081
+ <div class="kj-chat-code">
3082
+ <div class="kj-chat-code__bar">
3083
+ <span class="kj-chat-code__lang">{{ block.lang || 'code' }}</span>
3084
+ <button
3085
+ type="button"
3086
+ class="kj-chat-code__copy"
3087
+ [attr.aria-label]="copiedIndex() === $index ? 'Copied' : 'Copy code'"
3088
+ (click)="copy(block.code, $index)"
3089
+ >
3090
+ {{ copiedIndex() === $index ? 'Copied' : 'Copy' }}
3091
+ </button>
3092
+ </div>
3093
+ <pre class="kj-chat-code__pre"><code>{{ block.code }}</code></pre>
3094
+ </div>
3095
+ } @else {
3096
+ <div class="kj-chat-md" [innerHTML]="safe(block.html)"></div>
3097
+ }
3098
+ }
3099
+
3100
+ <!-- Typing indicator while streaming with no content yet -->
3101
+ @if (message().streaming && message().content.length === 0) {
3102
+ <div class="kj-chat-typing" role="status" aria-label="Assistant is typing">
3103
+ <span class="kj-chat-typing__dot"></span>
3104
+ <span class="kj-chat-typing__dot"></span>
3105
+ <span class="kj-chat-typing__dot"></span>
3106
+ </div>
3107
+ }
3108
+ </div>
3109
+
3110
+ <!-- Error -->
3111
+ @if (message().error) {
3112
+ <p class="kj-chat-msg__error" role="alert">{{ message().error }}</p>
3113
+ }
3114
+
3115
+ <!-- Citations -->
3116
+ @if ((message().citations ?? []).length > 0) {
3117
+ <ul class="kj-chat-cites" aria-label="Sources">
3118
+ @for (c of message().citations ?? []; track c.id) {
3119
+ <li class="kj-chat-cite">
3120
+ @if (c.url) {
3121
+ <a
3122
+ class="kj-chat-cite__link"
3123
+ [href]="c.url"
3124
+ rel="noopener noreferrer"
3125
+ target="_blank"
3126
+ >{{ c.title }}</a
3127
+ >
3128
+ } @else {
3129
+ <span class="kj-chat-cite__link">{{ c.title }}</span>
3130
+ }
3131
+ @if (c.snippet) {
3132
+ <span class="kj-chat-cite__snippet">{{ c.snippet }}</span>
3133
+ }
3134
+ </li>
3135
+ }
3136
+ </ul>
3137
+ }
3138
+ </div>
3139
+ </div>
3140
+ `, isInline: true, styles: ["@layer kj.component{.kj-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-chat-thread{display:flex;flex-direction:column;gap:var(--kj-space-md);padding:var(--kj-space-md);background:var(--kj-bg-body);color:var(--kj-fg-default);border-radius:var(--kj-radius-box);overflow-y:auto;font-family:var(--kj-font-sans)}.kj-chat-msg{display:flex;gap:var(--kj-space-sm);align-items:flex-start;max-width:100%}.kj-chat-msg[data-side=end]{flex-direction:row-reverse;margin-inline-start:auto}.kj-chat-msg[data-role=system]{justify-content:center}.kj-chat-msg__avatar{flex:0 0 auto;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;font-size:var(--kj-text-sm);font-weight:600;background:var(--kj-bg-surface);color:var(--kj-fg-default);border:1px solid var(--kj-border-default)}.kj-chat-msg__bubble{display:flex;flex-direction:column;gap:var(--kj-space-xs);padding:var(--kj-space-sm) var(--kj-space-md);border-radius:var(--kj-radius-box);background:var(--kj-bg-surface);color:var(--kj-fg-default);max-width:min(48rem,100%);overflow-wrap:anywhere}.kj-chat-msg[data-role=user] .kj-chat-msg__bubble{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-chat-msg[data-role=system] .kj-chat-msg__bubble{background:transparent;color:var(--kj-fg-muted);font-size:var(--kj-text-sm);text-align:center;padding-block:var(--kj-space-xs)}.kj-chat-msg__body :is(p){margin:0 0 var(--kj-space-xs)}.kj-chat-msg__body :is(p):last-child{margin-bottom:0}.kj-chat-msg__error{margin:0;color:var(--kj-fg-danger);font-size:var(--kj-text-sm)}.kj-md-link{color:inherit;text-decoration:underline}.kj-md-code{font-family:ui-monospace,monospace;background:color-mix(in srgb,currentColor 12%,transparent);padding:.1em .35em;border-radius:var(--kj-radius-field);font-size:.9em}.kj-chat-code{border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);overflow:hidden;margin:var(--kj-space-xs) 0;background:var(--kj-bg-body)}.kj-chat-code__bar{display:flex;align-items:center;justify-content:space-between;padding:.25rem var(--kj-space-sm);background:var(--kj-bg-surface);border-bottom:1px solid var(--kj-border-default);font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-chat-code__copy{min-height:1.75rem;padding:.25rem .6rem;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);color:var(--kj-fg-default);font-size:var(--kj-text-sm);cursor:pointer}.kj-chat-code__copy:hover{background:var(--kj-bg-surface)}.kj-chat-code__copy:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-chat-code__pre{margin:0;padding:var(--kj-space-sm);overflow-x:auto;font-family:ui-monospace,monospace;font-size:.9em;color:var(--kj-fg-default)}.kj-chat-tool{display:flex;align-items:center;gap:var(--kj-space-xs);padding:.35rem var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);font-size:var(--kj-text-sm)}.kj-chat-tool__name{font-weight:600;font-family:ui-monospace,monospace}.kj-chat-tool__status{margin-inline-start:auto;color:var(--kj-fg-muted);text-transform:capitalize}.kj-chat-tool[data-status=error]{border-color:var(--kj-border-danger)}.kj-chat-tool[data-status=error] .kj-chat-tool__status,.kj-chat-tool__error{color:var(--kj-fg-danger)}.kj-chat-cites{list-style:none;margin:var(--kj-space-xs) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--kj-space-xs)}.kj-chat-cite{display:inline-flex;align-items:baseline;gap:.35rem;padding:.15rem .5rem;border:1px solid var(--kj-border-default);border-radius:999px;font-size:var(--kj-text-sm);background:var(--kj-bg-body)}.kj-chat-cite__link{color:var(--kj-fg-info);text-decoration:none}.kj-chat-cite__link:hover{text-decoration:underline}.kj-chat-cite__snippet{color:var(--kj-fg-muted)}.kj-chat-typing{display:inline-flex;gap:.25rem;align-items:center;padding:.25rem 0}.kj-chat-typing__dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--kj-fg-muted);animation:kj-chat-bounce 1.2s infinite ease-in-out both}.kj-chat-typing__dot:nth-child(2){animation-delay:.15s}.kj-chat-typing__dot:nth-child(3){animation-delay:.3s}@keyframes kj-chat-bounce{0%,80%,to{transform:scale(.5);opacity:.4}40%{transform:scale(1);opacity:1}}@media(prefers-reduced-motion:reduce){.kj-chat-typing__dot{animation:none;opacity:.6}}.kj-prompt{position:relative;display:flex;align-items:flex-end;gap:var(--kj-space-sm);padding:var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-box);background:var(--kj-bg-field, var(--kj-input-bg))}.kj-prompt:focus-within{border-color:var(--kj-border-focus)}.kj-prompt__textarea{flex:1 1 auto;resize:none;border:none;outline:none;background:transparent;color:var(--kj-input-fg, var(--kj-fg-default));font-family:var(--kj-font-sans);font-size:var(--kj-input-font-size, 1rem);line-height:1.5;max-height:200px;overflow-y:auto}.kj-prompt__textarea::placeholder{color:var(--kj-input-placeholder-fg, var(--kj-fg-muted))}.kj-prompt__actions{display:flex;align-items:center;gap:var(--kj-space-xs);flex:0 0 auto}.kj-prompt__btn{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;border:none;cursor:pointer;font-size:1.1rem}.kj-prompt__btn:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-prompt__btn--send{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__btn--send:disabled{opacity:.5;cursor:not-allowed}.kj-prompt__btn--stop{background:var(--kj-bg-danger);color:var(--kj-fg-on-danger)}.kj-prompt__slash{position:absolute;bottom:calc(100% + .25rem);left:0;right:0;margin:0;padding:.25rem;list-style:none;background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);box-shadow:0 4px 16px #00000026;max-height:14rem;overflow-y:auto;z-index:10}.kj-prompt__slash-item{display:flex;flex-direction:column;gap:.1rem;padding:var(--kj-space-xs) var(--kj-space-sm);border-radius:var(--kj-radius-field);cursor:pointer}.kj-prompt__slash-item.is-active,.kj-prompt__slash-item:hover{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__slash-name{font-family:ui-monospace,monospace;font-weight:600}.kj-prompt__slash-desc{font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-prompt__slash-item.is-active .kj-prompt__slash-desc,.kj-prompt__slash-item:hover .kj-prompt__slash-desc{color:inherit}}\n"], dependencies: [{ kind: "directive", type: KjChat, selector: "[kjChat]", inputs: ["kjSide", "kjChatAuthor", "kjChatGrouped", "kjRole"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3141
+ }
3142
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjChatMessage, decorators: [{
3143
+ type: Component,
3144
+ args: [{ selector: 'kj-chat-message', standalone: true, imports: [KjChat], template: `
3145
+ <div
3146
+ kjChat
3147
+ class="kj-chat-msg"
3148
+ [kjSide]="side()"
3149
+ [attr.data-role]="message().role"
3150
+ [attr.aria-label]="roleLabel()"
3151
+ >
3152
+ @if (showAvatar()) {
3153
+ <div class="kj-chat-msg__avatar" aria-hidden="true">{{ avatarGlyph() }}</div>
3154
+ }
3155
+
3156
+ <div class="kj-chat-msg__bubble">
3157
+ <!-- Tool-call cards (assistant turns) -->
3158
+ @for (tc of message().toolCalls ?? []; track tc.id) {
3159
+ <div
3160
+ class="kj-chat-tool"
3161
+ [attr.data-status]="tc.status"
3162
+ role="group"
3163
+ [attr.aria-label]="'Tool call: ' + tc.name"
3164
+ >
3165
+ <span class="kj-chat-tool__icon" aria-hidden="true">⚙</span>
3166
+ <span class="kj-chat-tool__name">{{ tc.name }}</span>
3167
+ <span class="kj-chat-tool__status">{{ tc.status }}</span>
3168
+ @if (tc.error) {
3169
+ <span class="kj-chat-tool__error">{{ tc.error }}</span>
3170
+ }
3171
+ </div>
3172
+ }
3173
+
3174
+ <!-- Body -->
3175
+ <div class="kj-chat-msg__body">
3176
+ @for (block of blocks(); track $index) {
3177
+ @if (block.kind === 'code') {
3178
+ <div class="kj-chat-code">
3179
+ <div class="kj-chat-code__bar">
3180
+ <span class="kj-chat-code__lang">{{ block.lang || 'code' }}</span>
3181
+ <button
3182
+ type="button"
3183
+ class="kj-chat-code__copy"
3184
+ [attr.aria-label]="copiedIndex() === $index ? 'Copied' : 'Copy code'"
3185
+ (click)="copy(block.code, $index)"
3186
+ >
3187
+ {{ copiedIndex() === $index ? 'Copied' : 'Copy' }}
3188
+ </button>
3189
+ </div>
3190
+ <pre class="kj-chat-code__pre"><code>{{ block.code }}</code></pre>
3191
+ </div>
3192
+ } @else {
3193
+ <div class="kj-chat-md" [innerHTML]="safe(block.html)"></div>
3194
+ }
3195
+ }
3196
+
3197
+ <!-- Typing indicator while streaming with no content yet -->
3198
+ @if (message().streaming && message().content.length === 0) {
3199
+ <div class="kj-chat-typing" role="status" aria-label="Assistant is typing">
3200
+ <span class="kj-chat-typing__dot"></span>
3201
+ <span class="kj-chat-typing__dot"></span>
3202
+ <span class="kj-chat-typing__dot"></span>
3203
+ </div>
3204
+ }
3205
+ </div>
3206
+
3207
+ <!-- Error -->
3208
+ @if (message().error) {
3209
+ <p class="kj-chat-msg__error" role="alert">{{ message().error }}</p>
3210
+ }
3211
+
3212
+ <!-- Citations -->
3213
+ @if ((message().citations ?? []).length > 0) {
3214
+ <ul class="kj-chat-cites" aria-label="Sources">
3215
+ @for (c of message().citations ?? []; track c.id) {
3216
+ <li class="kj-chat-cite">
3217
+ @if (c.url) {
3218
+ <a
3219
+ class="kj-chat-cite__link"
3220
+ [href]="c.url"
3221
+ rel="noopener noreferrer"
3222
+ target="_blank"
3223
+ >{{ c.title }}</a
3224
+ >
3225
+ } @else {
3226
+ <span class="kj-chat-cite__link">{{ c.title }}</span>
3227
+ }
3228
+ @if (c.snippet) {
3229
+ <span class="kj-chat-cite__snippet">{{ c.snippet }}</span>
3230
+ }
3231
+ </li>
3232
+ }
3233
+ </ul>
3234
+ }
3235
+ </div>
3236
+ </div>
3237
+ `, encapsulation: ViewEncapsulation.None, host: { class: 'kj-chat-msg-host' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-chat-thread{display:flex;flex-direction:column;gap:var(--kj-space-md);padding:var(--kj-space-md);background:var(--kj-bg-body);color:var(--kj-fg-default);border-radius:var(--kj-radius-box);overflow-y:auto;font-family:var(--kj-font-sans)}.kj-chat-msg{display:flex;gap:var(--kj-space-sm);align-items:flex-start;max-width:100%}.kj-chat-msg[data-side=end]{flex-direction:row-reverse;margin-inline-start:auto}.kj-chat-msg[data-role=system]{justify-content:center}.kj-chat-msg__avatar{flex:0 0 auto;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;font-size:var(--kj-text-sm);font-weight:600;background:var(--kj-bg-surface);color:var(--kj-fg-default);border:1px solid var(--kj-border-default)}.kj-chat-msg__bubble{display:flex;flex-direction:column;gap:var(--kj-space-xs);padding:var(--kj-space-sm) var(--kj-space-md);border-radius:var(--kj-radius-box);background:var(--kj-bg-surface);color:var(--kj-fg-default);max-width:min(48rem,100%);overflow-wrap:anywhere}.kj-chat-msg[data-role=user] .kj-chat-msg__bubble{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-chat-msg[data-role=system] .kj-chat-msg__bubble{background:transparent;color:var(--kj-fg-muted);font-size:var(--kj-text-sm);text-align:center;padding-block:var(--kj-space-xs)}.kj-chat-msg__body :is(p){margin:0 0 var(--kj-space-xs)}.kj-chat-msg__body :is(p):last-child{margin-bottom:0}.kj-chat-msg__error{margin:0;color:var(--kj-fg-danger);font-size:var(--kj-text-sm)}.kj-md-link{color:inherit;text-decoration:underline}.kj-md-code{font-family:ui-monospace,monospace;background:color-mix(in srgb,currentColor 12%,transparent);padding:.1em .35em;border-radius:var(--kj-radius-field);font-size:.9em}.kj-chat-code{border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);overflow:hidden;margin:var(--kj-space-xs) 0;background:var(--kj-bg-body)}.kj-chat-code__bar{display:flex;align-items:center;justify-content:space-between;padding:.25rem var(--kj-space-sm);background:var(--kj-bg-surface);border-bottom:1px solid var(--kj-border-default);font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-chat-code__copy{min-height:1.75rem;padding:.25rem .6rem;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);color:var(--kj-fg-default);font-size:var(--kj-text-sm);cursor:pointer}.kj-chat-code__copy:hover{background:var(--kj-bg-surface)}.kj-chat-code__copy:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-chat-code__pre{margin:0;padding:var(--kj-space-sm);overflow-x:auto;font-family:ui-monospace,monospace;font-size:.9em;color:var(--kj-fg-default)}.kj-chat-tool{display:flex;align-items:center;gap:var(--kj-space-xs);padding:.35rem var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);font-size:var(--kj-text-sm)}.kj-chat-tool__name{font-weight:600;font-family:ui-monospace,monospace}.kj-chat-tool__status{margin-inline-start:auto;color:var(--kj-fg-muted);text-transform:capitalize}.kj-chat-tool[data-status=error]{border-color:var(--kj-border-danger)}.kj-chat-tool[data-status=error] .kj-chat-tool__status,.kj-chat-tool__error{color:var(--kj-fg-danger)}.kj-chat-cites{list-style:none;margin:var(--kj-space-xs) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--kj-space-xs)}.kj-chat-cite{display:inline-flex;align-items:baseline;gap:.35rem;padding:.15rem .5rem;border:1px solid var(--kj-border-default);border-radius:999px;font-size:var(--kj-text-sm);background:var(--kj-bg-body)}.kj-chat-cite__link{color:var(--kj-fg-info);text-decoration:none}.kj-chat-cite__link:hover{text-decoration:underline}.kj-chat-cite__snippet{color:var(--kj-fg-muted)}.kj-chat-typing{display:inline-flex;gap:.25rem;align-items:center;padding:.25rem 0}.kj-chat-typing__dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--kj-fg-muted);animation:kj-chat-bounce 1.2s infinite ease-in-out both}.kj-chat-typing__dot:nth-child(2){animation-delay:.15s}.kj-chat-typing__dot:nth-child(3){animation-delay:.3s}@keyframes kj-chat-bounce{0%,80%,to{transform:scale(.5);opacity:.4}40%{transform:scale(1);opacity:1}}@media(prefers-reduced-motion:reduce){.kj-chat-typing__dot{animation:none;opacity:.6}}.kj-prompt{position:relative;display:flex;align-items:flex-end;gap:var(--kj-space-sm);padding:var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-box);background:var(--kj-bg-field, var(--kj-input-bg))}.kj-prompt:focus-within{border-color:var(--kj-border-focus)}.kj-prompt__textarea{flex:1 1 auto;resize:none;border:none;outline:none;background:transparent;color:var(--kj-input-fg, var(--kj-fg-default));font-family:var(--kj-font-sans);font-size:var(--kj-input-font-size, 1rem);line-height:1.5;max-height:200px;overflow-y:auto}.kj-prompt__textarea::placeholder{color:var(--kj-input-placeholder-fg, var(--kj-fg-muted))}.kj-prompt__actions{display:flex;align-items:center;gap:var(--kj-space-xs);flex:0 0 auto}.kj-prompt__btn{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;border:none;cursor:pointer;font-size:1.1rem}.kj-prompt__btn:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-prompt__btn--send{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__btn--send:disabled{opacity:.5;cursor:not-allowed}.kj-prompt__btn--stop{background:var(--kj-bg-danger);color:var(--kj-fg-on-danger)}.kj-prompt__slash{position:absolute;bottom:calc(100% + .25rem);left:0;right:0;margin:0;padding:.25rem;list-style:none;background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);box-shadow:0 4px 16px #00000026;max-height:14rem;overflow-y:auto;z-index:10}.kj-prompt__slash-item{display:flex;flex-direction:column;gap:.1rem;padding:var(--kj-space-xs) var(--kj-space-sm);border-radius:var(--kj-radius-field);cursor:pointer}.kj-prompt__slash-item.is-active,.kj-prompt__slash-item:hover{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__slash-name{font-family:ui-monospace,monospace;font-weight:600}.kj-prompt__slash-desc{font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-prompt__slash-item.is-active .kj-prompt__slash-desc,.kj-prompt__slash-item:hover .kj-prompt__slash-desc{color:inherit}}\n"] }]
3238
+ }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }] } });
3239
+
3240
+ /**
3241
+ * The AI thread surface: a scrollable message log driven by a {@link KjChatStore}.
3242
+ *
3243
+ * **Reuses `KjChatLog`** (core) for the `role="log"` message-log container, but
3244
+ * sets `kjChatLogLive="off"` because streamed tokens mutate an *existing*
3245
+ * message node — announcing every mutation would spam AT. Instead a single
3246
+ * dedicated **visually-hidden `aria-live="polite"` region** carries
3247
+ * announcements, fed by {@link KjChatAnnouncer}'s **coalescer** so the reply is
3248
+ * announced as whole sentences (never char-by-char, never duplicated). This is
3249
+ * the kit's accessibility differentiator.
3250
+ *
3251
+ * Provider-agnostic: pair with `KjPromptInput` and drive `KjChatStore` from any
3252
+ * model / stream — the kit ships **no** LLM SDK or backend.
3253
+ *
3254
+ * @doc-example Streaming (simulated)
3255
+ * A full send → simulated-stream → reply loop with slash commands, a Stop
3256
+ * button, tool-call cards and citations. No backend — a fake token generator
3257
+ * feeds the store on a timer.
3258
+ * @doc-file ai-chat.example.ts
2576
3259
  *
2577
3260
  * @doc-keyboard
2578
- * Space Toggles the checked state
2579
- * Tab Moves focus to the next focusable element
3261
+ * Enter Send the message
3262
+ * Shift+Enter Insert a newline
3263
+ * Esc — Stop generating (while streaming) / close the slash menu
3264
+ * ArrowUp/Down — Move the slash-command selection
2580
3265
  *
2581
3266
  * @doc-aria
2582
- * role="checkbox" Applied to the inner focusable box by the headless directive
2583
- * aria-checked Reflects `true`, `false`, or `"mixed"` for indeterminate
2584
- * aria-disabled — Reflected when `[disabled]` is true
2585
- * aria-labelledby Auto-wired to the projected label span
2586
- * data-disabled — Mirrors the disabled posture for theme/scope hooks
2587
- * data-indeterminate — Reflects the indeterminate posture for the dash glyph
3267
+ * role `log` on the thread container (reuses `KjChatLog`)
3268
+ * aria-live — `off` on the visible log; a dedicated visually-hidden
3269
+ * `polite` region carries coalesced sentence announcements
3270
+ * article each message is an `article` (via `KjChat`) named by its role
2588
3271
  *
2589
- * @doc-css-var
2590
- * --kj-checkbox-size — Box edge length. `data-size="sm|lg"` overrides; default 1rem.
2591
- * --kj-checkbox-bg Unchecked background fill. Defaults to --kj-bg-body.
3272
+ * @doc-a11y
3273
+ * Streaming replies are announced by a coalesced polite live region on
3274
+ * sentence boundaries — never char-by-char so screen-reader users hear
3275
+ * whole sentences once each. Keyboard send/stop, reduced-motion typing dots,
3276
+ * and ≥44px controls complete the AAA story.
3277
+ *
3278
+ * @doc-related chat,command-palette,textarea
3279
+ *
3280
+ * @doc-category Library/AI
3281
+ * @doc
3282
+ * @doc-name ai-chat
3283
+ * @doc-is-main
3284
+ * @doc-description Provider-agnostic AI chat thread with streaming append, coalesced live-region announcements, slash commands, tool-call cards, and citations.
3285
+ */
3286
+ class KjChatThread {
3287
+ /** The store driving this thread. */
3288
+ store = input.required(/* @ts-ignore */
3289
+ ...(ngDevMode ? [{ debugName: "store" }] : /* istanbul ignore next */ []));
3290
+ /** Accessible label for the log landmark. */
3291
+ kjLabel = input('Conversation', /* @ts-ignore */
3292
+ ...(ngDevMode ? [{ debugName: "kjLabel" }] : /* istanbul ignore next */ []));
3293
+ /** @internal — the coalescing announcer for the polite live region. */
3294
+ announcer = inject(KjChatAnnouncer);
3295
+ injector = inject(Injector);
3296
+ logEl = viewChild.required('log');
3297
+ lastId = null;
3298
+ lastLen = 0;
3299
+ prevStatus = null;
3300
+ constructor() {
3301
+ // Feed streamed deltas into the coalescer and manage flush/error/scroll.
3302
+ effect(() => {
3303
+ const store = this.store();
3304
+ const msgs = store.messages();
3305
+ const sid = store.streamingId();
3306
+ const status = store.status();
3307
+ untracked(() => {
3308
+ // New stream started — reset the delta cursor.
3309
+ if (sid !== this.lastId) {
3310
+ this.lastId = sid;
3311
+ this.lastLen = 0;
3312
+ }
3313
+ // Push the newly-arrived text delta to the coalescer.
3314
+ if (sid) {
3315
+ const m = msgs.find((x) => x.id === sid);
3316
+ if (m) {
3317
+ const delta = m.content.slice(this.lastLen);
3318
+ this.lastLen = m.content.length;
3319
+ if (delta)
3320
+ this.announcer.push(delta);
3321
+ }
3322
+ }
3323
+ // Status transitions: flush remainder on completion, announce errors.
3324
+ if (this.prevStatus === 'streaming' && status !== 'streaming') {
3325
+ this.announcer.flush();
3326
+ if (status === 'error')
3327
+ this.announcer.announce('Response failed.');
3328
+ }
3329
+ this.prevStatus = status;
3330
+ this.scrollToBottom();
3331
+ });
3332
+ });
3333
+ }
3334
+ scrollToBottom() {
3335
+ afterNextRender(() => {
3336
+ const el = this.logEl().nativeElement;
3337
+ el.scrollTop = el.scrollHeight;
3338
+ }, { injector: this.injector });
3339
+ }
3340
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjChatThread, deps: [], target: i0.ɵɵFactoryTarget.Component });
3341
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjChatThread, isStandalone: true, selector: "kj-chat-thread", inputs: { store: { classPropertyName: "store", publicName: "store", isSignal: true, isRequired: true, transformFunction: null }, kjLabel: { classPropertyName: "kjLabel", publicName: "kjLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "kj-chat-thread-host" }, providers: [KjChatAnnouncer], viewQueries: [{ propertyName: "logEl", first: true, predicate: ["log"], descendants: true, isSignal: true }], ngImport: i0, template: `
3342
+ <div #log kjChatLog kjChatLogLive="off" class="kj-chat-thread" [kjChatLogLabel]="kjLabel()">
3343
+ @for (m of store().messages(); track m.id) {
3344
+ <kj-chat-message [message]="m" />
3345
+ }
3346
+ </div>
3347
+
3348
+ <!-- Coalesced polite announcer: whole sentences, debounced by boundary. -->
3349
+ <div class="kj-visually-hidden" aria-live="polite" aria-atomic="false">
3350
+ {{ announcer.message() }}
3351
+ </div>
3352
+ `, isInline: true, styles: ["@layer kj.component{.kj-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-chat-thread{display:flex;flex-direction:column;gap:var(--kj-space-md);padding:var(--kj-space-md);background:var(--kj-bg-body);color:var(--kj-fg-default);border-radius:var(--kj-radius-box);overflow-y:auto;font-family:var(--kj-font-sans)}.kj-chat-msg{display:flex;gap:var(--kj-space-sm);align-items:flex-start;max-width:100%}.kj-chat-msg[data-side=end]{flex-direction:row-reverse;margin-inline-start:auto}.kj-chat-msg[data-role=system]{justify-content:center}.kj-chat-msg__avatar{flex:0 0 auto;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;font-size:var(--kj-text-sm);font-weight:600;background:var(--kj-bg-surface);color:var(--kj-fg-default);border:1px solid var(--kj-border-default)}.kj-chat-msg__bubble{display:flex;flex-direction:column;gap:var(--kj-space-xs);padding:var(--kj-space-sm) var(--kj-space-md);border-radius:var(--kj-radius-box);background:var(--kj-bg-surface);color:var(--kj-fg-default);max-width:min(48rem,100%);overflow-wrap:anywhere}.kj-chat-msg[data-role=user] .kj-chat-msg__bubble{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-chat-msg[data-role=system] .kj-chat-msg__bubble{background:transparent;color:var(--kj-fg-muted);font-size:var(--kj-text-sm);text-align:center;padding-block:var(--kj-space-xs)}.kj-chat-msg__body :is(p){margin:0 0 var(--kj-space-xs)}.kj-chat-msg__body :is(p):last-child{margin-bottom:0}.kj-chat-msg__error{margin:0;color:var(--kj-fg-danger);font-size:var(--kj-text-sm)}.kj-md-link{color:inherit;text-decoration:underline}.kj-md-code{font-family:ui-monospace,monospace;background:color-mix(in srgb,currentColor 12%,transparent);padding:.1em .35em;border-radius:var(--kj-radius-field);font-size:.9em}.kj-chat-code{border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);overflow:hidden;margin:var(--kj-space-xs) 0;background:var(--kj-bg-body)}.kj-chat-code__bar{display:flex;align-items:center;justify-content:space-between;padding:.25rem var(--kj-space-sm);background:var(--kj-bg-surface);border-bottom:1px solid var(--kj-border-default);font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-chat-code__copy{min-height:1.75rem;padding:.25rem .6rem;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);color:var(--kj-fg-default);font-size:var(--kj-text-sm);cursor:pointer}.kj-chat-code__copy:hover{background:var(--kj-bg-surface)}.kj-chat-code__copy:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-chat-code__pre{margin:0;padding:var(--kj-space-sm);overflow-x:auto;font-family:ui-monospace,monospace;font-size:.9em;color:var(--kj-fg-default)}.kj-chat-tool{display:flex;align-items:center;gap:var(--kj-space-xs);padding:.35rem var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);font-size:var(--kj-text-sm)}.kj-chat-tool__name{font-weight:600;font-family:ui-monospace,monospace}.kj-chat-tool__status{margin-inline-start:auto;color:var(--kj-fg-muted);text-transform:capitalize}.kj-chat-tool[data-status=error]{border-color:var(--kj-border-danger)}.kj-chat-tool[data-status=error] .kj-chat-tool__status,.kj-chat-tool__error{color:var(--kj-fg-danger)}.kj-chat-cites{list-style:none;margin:var(--kj-space-xs) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--kj-space-xs)}.kj-chat-cite{display:inline-flex;align-items:baseline;gap:.35rem;padding:.15rem .5rem;border:1px solid var(--kj-border-default);border-radius:999px;font-size:var(--kj-text-sm);background:var(--kj-bg-body)}.kj-chat-cite__link{color:var(--kj-fg-info);text-decoration:none}.kj-chat-cite__link:hover{text-decoration:underline}.kj-chat-cite__snippet{color:var(--kj-fg-muted)}.kj-chat-typing{display:inline-flex;gap:.25rem;align-items:center;padding:.25rem 0}.kj-chat-typing__dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--kj-fg-muted);animation:kj-chat-bounce 1.2s infinite ease-in-out both}.kj-chat-typing__dot:nth-child(2){animation-delay:.15s}.kj-chat-typing__dot:nth-child(3){animation-delay:.3s}@keyframes kj-chat-bounce{0%,80%,to{transform:scale(.5);opacity:.4}40%{transform:scale(1);opacity:1}}@media(prefers-reduced-motion:reduce){.kj-chat-typing__dot{animation:none;opacity:.6}}.kj-prompt{position:relative;display:flex;align-items:flex-end;gap:var(--kj-space-sm);padding:var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-box);background:var(--kj-bg-field, var(--kj-input-bg))}.kj-prompt:focus-within{border-color:var(--kj-border-focus)}.kj-prompt__textarea{flex:1 1 auto;resize:none;border:none;outline:none;background:transparent;color:var(--kj-input-fg, var(--kj-fg-default));font-family:var(--kj-font-sans);font-size:var(--kj-input-font-size, 1rem);line-height:1.5;max-height:200px;overflow-y:auto}.kj-prompt__textarea::placeholder{color:var(--kj-input-placeholder-fg, var(--kj-fg-muted))}.kj-prompt__actions{display:flex;align-items:center;gap:var(--kj-space-xs);flex:0 0 auto}.kj-prompt__btn{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;border:none;cursor:pointer;font-size:1.1rem}.kj-prompt__btn:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-prompt__btn--send{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__btn--send:disabled{opacity:.5;cursor:not-allowed}.kj-prompt__btn--stop{background:var(--kj-bg-danger);color:var(--kj-fg-on-danger)}.kj-prompt__slash{position:absolute;bottom:calc(100% + .25rem);left:0;right:0;margin:0;padding:.25rem;list-style:none;background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);box-shadow:0 4px 16px #00000026;max-height:14rem;overflow-y:auto;z-index:10}.kj-prompt__slash-item{display:flex;flex-direction:column;gap:.1rem;padding:var(--kj-space-xs) var(--kj-space-sm);border-radius:var(--kj-radius-field);cursor:pointer}.kj-prompt__slash-item.is-active,.kj-prompt__slash-item:hover{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__slash-name{font-family:ui-monospace,monospace;font-weight:600}.kj-prompt__slash-desc{font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-prompt__slash-item.is-active .kj-prompt__slash-desc,.kj-prompt__slash-item:hover .kj-prompt__slash-desc{color:inherit}}\n"], dependencies: [{ kind: "directive", type: KjChatLog, selector: "[kjChatLog]", inputs: ["kjChatLogLive", "kjChatLogLabel"] }, { kind: "component", type: KjChatMessage, selector: "kj-chat-message", inputs: ["message"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3353
+ }
3354
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjChatThread, decorators: [{
3355
+ type: Component,
3356
+ args: [{ selector: 'kj-chat-thread', standalone: true, imports: [KjChatLog, KjChatMessage], providers: [KjChatAnnouncer], template: `
3357
+ <div #log kjChatLog kjChatLogLive="off" class="kj-chat-thread" [kjChatLogLabel]="kjLabel()">
3358
+ @for (m of store().messages(); track m.id) {
3359
+ <kj-chat-message [message]="m" />
3360
+ }
3361
+ </div>
3362
+
3363
+ <!-- Coalesced polite announcer: whole sentences, debounced by boundary. -->
3364
+ <div class="kj-visually-hidden" aria-live="polite" aria-atomic="false">
3365
+ {{ announcer.message() }}
3366
+ </div>
3367
+ `, encapsulation: ViewEncapsulation.None, host: { class: 'kj-chat-thread-host' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-chat-thread{display:flex;flex-direction:column;gap:var(--kj-space-md);padding:var(--kj-space-md);background:var(--kj-bg-body);color:var(--kj-fg-default);border-radius:var(--kj-radius-box);overflow-y:auto;font-family:var(--kj-font-sans)}.kj-chat-msg{display:flex;gap:var(--kj-space-sm);align-items:flex-start;max-width:100%}.kj-chat-msg[data-side=end]{flex-direction:row-reverse;margin-inline-start:auto}.kj-chat-msg[data-role=system]{justify-content:center}.kj-chat-msg__avatar{flex:0 0 auto;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;font-size:var(--kj-text-sm);font-weight:600;background:var(--kj-bg-surface);color:var(--kj-fg-default);border:1px solid var(--kj-border-default)}.kj-chat-msg__bubble{display:flex;flex-direction:column;gap:var(--kj-space-xs);padding:var(--kj-space-sm) var(--kj-space-md);border-radius:var(--kj-radius-box);background:var(--kj-bg-surface);color:var(--kj-fg-default);max-width:min(48rem,100%);overflow-wrap:anywhere}.kj-chat-msg[data-role=user] .kj-chat-msg__bubble{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-chat-msg[data-role=system] .kj-chat-msg__bubble{background:transparent;color:var(--kj-fg-muted);font-size:var(--kj-text-sm);text-align:center;padding-block:var(--kj-space-xs)}.kj-chat-msg__body :is(p){margin:0 0 var(--kj-space-xs)}.kj-chat-msg__body :is(p):last-child{margin-bottom:0}.kj-chat-msg__error{margin:0;color:var(--kj-fg-danger);font-size:var(--kj-text-sm)}.kj-md-link{color:inherit;text-decoration:underline}.kj-md-code{font-family:ui-monospace,monospace;background:color-mix(in srgb,currentColor 12%,transparent);padding:.1em .35em;border-radius:var(--kj-radius-field);font-size:.9em}.kj-chat-code{border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);overflow:hidden;margin:var(--kj-space-xs) 0;background:var(--kj-bg-body)}.kj-chat-code__bar{display:flex;align-items:center;justify-content:space-between;padding:.25rem var(--kj-space-sm);background:var(--kj-bg-surface);border-bottom:1px solid var(--kj-border-default);font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-chat-code__copy{min-height:1.75rem;padding:.25rem .6rem;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);color:var(--kj-fg-default);font-size:var(--kj-text-sm);cursor:pointer}.kj-chat-code__copy:hover{background:var(--kj-bg-surface)}.kj-chat-code__copy:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-chat-code__pre{margin:0;padding:var(--kj-space-sm);overflow-x:auto;font-family:ui-monospace,monospace;font-size:.9em;color:var(--kj-fg-default)}.kj-chat-tool{display:flex;align-items:center;gap:var(--kj-space-xs);padding:.35rem var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);font-size:var(--kj-text-sm)}.kj-chat-tool__name{font-weight:600;font-family:ui-monospace,monospace}.kj-chat-tool__status{margin-inline-start:auto;color:var(--kj-fg-muted);text-transform:capitalize}.kj-chat-tool[data-status=error]{border-color:var(--kj-border-danger)}.kj-chat-tool[data-status=error] .kj-chat-tool__status,.kj-chat-tool__error{color:var(--kj-fg-danger)}.kj-chat-cites{list-style:none;margin:var(--kj-space-xs) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--kj-space-xs)}.kj-chat-cite{display:inline-flex;align-items:baseline;gap:.35rem;padding:.15rem .5rem;border:1px solid var(--kj-border-default);border-radius:999px;font-size:var(--kj-text-sm);background:var(--kj-bg-body)}.kj-chat-cite__link{color:var(--kj-fg-info);text-decoration:none}.kj-chat-cite__link:hover{text-decoration:underline}.kj-chat-cite__snippet{color:var(--kj-fg-muted)}.kj-chat-typing{display:inline-flex;gap:.25rem;align-items:center;padding:.25rem 0}.kj-chat-typing__dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--kj-fg-muted);animation:kj-chat-bounce 1.2s infinite ease-in-out both}.kj-chat-typing__dot:nth-child(2){animation-delay:.15s}.kj-chat-typing__dot:nth-child(3){animation-delay:.3s}@keyframes kj-chat-bounce{0%,80%,to{transform:scale(.5);opacity:.4}40%{transform:scale(1);opacity:1}}@media(prefers-reduced-motion:reduce){.kj-chat-typing__dot{animation:none;opacity:.6}}.kj-prompt{position:relative;display:flex;align-items:flex-end;gap:var(--kj-space-sm);padding:var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-box);background:var(--kj-bg-field, var(--kj-input-bg))}.kj-prompt:focus-within{border-color:var(--kj-border-focus)}.kj-prompt__textarea{flex:1 1 auto;resize:none;border:none;outline:none;background:transparent;color:var(--kj-input-fg, var(--kj-fg-default));font-family:var(--kj-font-sans);font-size:var(--kj-input-font-size, 1rem);line-height:1.5;max-height:200px;overflow-y:auto}.kj-prompt__textarea::placeholder{color:var(--kj-input-placeholder-fg, var(--kj-fg-muted))}.kj-prompt__actions{display:flex;align-items:center;gap:var(--kj-space-xs);flex:0 0 auto}.kj-prompt__btn{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;border:none;cursor:pointer;font-size:1.1rem}.kj-prompt__btn:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-prompt__btn--send{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__btn--send:disabled{opacity:.5;cursor:not-allowed}.kj-prompt__btn--stop{background:var(--kj-bg-danger);color:var(--kj-fg-on-danger)}.kj-prompt__slash{position:absolute;bottom:calc(100% + .25rem);left:0;right:0;margin:0;padding:.25rem;list-style:none;background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);box-shadow:0 4px 16px #00000026;max-height:14rem;overflow-y:auto;z-index:10}.kj-prompt__slash-item{display:flex;flex-direction:column;gap:.1rem;padding:var(--kj-space-xs) var(--kj-space-sm);border-radius:var(--kj-radius-field);cursor:pointer}.kj-prompt__slash-item.is-active,.kj-prompt__slash-item:hover{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__slash-name{font-family:ui-monospace,monospace;font-weight:600}.kj-prompt__slash-desc{font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-prompt__slash-item.is-active .kj-prompt__slash-desc,.kj-prompt__slash-item:hover .kj-prompt__slash-desc{color:inherit}}\n"] }]
3368
+ }], ctorParameters: () => [], propDecorators: { store: [{ type: i0.Input, args: [{ isSignal: true, alias: "store", required: true }] }], kjLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLabel", required: false }] }], logEl: [{ type: i0.ViewChild, args: ['log', { isSignal: true }] }] } });
3369
+
3370
+ let _promptId = 0;
3371
+ /**
3372
+ * Prompt composer for an AI thread: an auto-growing textarea with send / stop
3373
+ * controls, an optional attachment slot (`[kjPromptAttachments]`), and a
3374
+ * slash-command menu.
3375
+ *
3376
+ * **Keyboard:** `Enter` sends, `Shift+Enter` inserts a newline, `Esc` stops the
3377
+ * stream (when streaming) or closes the slash menu; `↑/↓` move the slash
3378
+ * selection and `Enter` picks it. The menu is a `role="listbox"`; the textarea
3379
+ * keeps DOM focus and points `aria-activedescendant` at the active option.
3380
+ *
3381
+ * **Slash matching reuses the command-palette engine** via
3382
+ * `matchSlashCommands` (backed by the palette's `kjSubstringFilter`).
3383
+ *
3384
+ * @doc
3385
+ * @doc-name ai-chat
3386
+ */
3387
+ class KjPromptInput {
3388
+ uid = ++_promptId;
3389
+ textareaId = `kj-prompt-${this.uid}`;
3390
+ listboxId = `kj-prompt-slash-${this.uid}`;
3391
+ /** Two-way bound draft text. */
3392
+ kjValue = model('', /* @ts-ignore */
3393
+ ...(ngDevMode ? [{ debugName: "kjValue" }] : /* istanbul ignore next */ []));
3394
+ /** Placeholder text. */
3395
+ kjPlaceholder = input('Message the assistant…', /* @ts-ignore */
3396
+ ...(ngDevMode ? [{ debugName: "kjPlaceholder" }] : /* istanbul ignore next */ []));
3397
+ /** Accessible label for the textarea. */
3398
+ kjLabel = input('Message', /* @ts-ignore */
3399
+ ...(ngDevMode ? [{ debugName: "kjLabel" }] : /* istanbul ignore next */ []));
3400
+ /** When true, show the Stop button instead of Send. */
3401
+ kjStreaming = input(false, /* @ts-ignore */
3402
+ ...(ngDevMode ? [{ debugName: "kjStreaming" }] : /* istanbul ignore next */ []));
3403
+ /** Disable the composer entirely. */
3404
+ kjDisabled = input(false, /* @ts-ignore */
3405
+ ...(ngDevMode ? [{ debugName: "kjDisabled" }] : /* istanbul ignore next */ []));
3406
+ /** Available slash commands. */
3407
+ kjSlashCommands = input([], /* @ts-ignore */
3408
+ ...(ngDevMode ? [{ debugName: "kjSlashCommands" }] : /* istanbul ignore next */ []));
3409
+ /** Emits the trimmed message text on send. */
3410
+ kjSend = output();
3411
+ /** Emits when the user requests a stop. */
3412
+ kjStop = output();
3413
+ /** Emits the picked slash command. */
3414
+ kjSlashSelect = output();
3415
+ ta = viewChild.required('ta');
3416
+ _active = signal(0, /* @ts-ignore */
3417
+ ...(ngDevMode ? [{ debugName: "_active" }] : /* istanbul ignore next */ []));
3418
+ activeIndex = this._active.asReadonly();
3419
+ slash = computed(() => parseSlash(this.kjValue()), /* @ts-ignore */
3420
+ ...(ngDevMode ? [{ debugName: "slash" }] : /* istanbul ignore next */ []));
3421
+ slashMatches = computed(() => {
3422
+ const s = this.slash();
3423
+ if (!s.active)
3424
+ return [];
3425
+ return matchSlashCommands(s.query, this.kjSlashCommands());
3426
+ }, /* @ts-ignore */
3427
+ ...(ngDevMode ? [{ debugName: "slashMatches" }] : /* istanbul ignore next */ []));
3428
+ slashOpen = computed(() => this.slashMatches().length > 0, /* @ts-ignore */
3429
+ ...(ngDevMode ? [{ debugName: "slashOpen" }] : /* istanbul ignore next */ []));
3430
+ constructor() {
3431
+ // Keep the active index in range as matches change.
3432
+ effect(() => {
3433
+ const n = this.slashMatches().length;
3434
+ if (this._active() >= n)
3435
+ this._active.set(0);
3436
+ });
3437
+ // Auto-grow whenever the value changes (incl. programmatic resets).
3438
+ effect(() => {
3439
+ this.kjValue();
3440
+ queueMicrotask(() => this.autogrow());
3441
+ });
3442
+ }
3443
+ optionId(i) {
3444
+ return `${this.listboxId}-opt-${i}`;
3445
+ }
3446
+ onInput(ev) {
3447
+ this.kjValue.set(ev.target.value);
3448
+ this.autogrow();
3449
+ }
3450
+ onKeydown(ev) {
3451
+ if (this.slashOpen()) {
3452
+ if (ev.key === 'ArrowDown') {
3453
+ ev.preventDefault();
3454
+ this._active.update((i) => (i + 1) % this.slashMatches().length);
3455
+ return;
3456
+ }
3457
+ if (ev.key === 'ArrowUp') {
3458
+ ev.preventDefault();
3459
+ const n = this.slashMatches().length;
3460
+ this._active.update((i) => (i - 1 + n) % n);
3461
+ return;
3462
+ }
3463
+ if (ev.key === 'Enter') {
3464
+ ev.preventDefault();
3465
+ const cmd = this.slashMatches()[this._active()];
3466
+ if (cmd)
3467
+ this.commitSlash(cmd);
3468
+ return;
3469
+ }
3470
+ if (ev.key === 'Escape') {
3471
+ ev.preventDefault();
3472
+ // Close the menu by clearing the in-progress slash token.
3473
+ this.kjValue.set('');
3474
+ return;
3475
+ }
3476
+ }
3477
+ if (ev.key === 'Enter' && !ev.shiftKey) {
3478
+ ev.preventDefault();
3479
+ this.send();
3480
+ return;
3481
+ }
3482
+ if (ev.key === 'Escape' && this.kjStreaming()) {
3483
+ ev.preventDefault();
3484
+ this.onStop();
3485
+ }
3486
+ }
3487
+ onSubmit(ev) {
3488
+ ev.preventDefault();
3489
+ this.send();
3490
+ }
3491
+ onStop() {
3492
+ this.kjStop.emit();
3493
+ }
3494
+ pickSlash(ev, cmd) {
3495
+ ev.preventDefault(); // keep textarea focus
3496
+ this.commitSlash(cmd);
3497
+ }
3498
+ commitSlash(cmd) {
3499
+ this.kjSlashSelect.emit(cmd);
3500
+ this.kjValue.set(cmd.name + ' ');
3501
+ this.ta().nativeElement.focus();
3502
+ }
3503
+ send() {
3504
+ const text = this.kjValue().trim();
3505
+ if (!text || this.kjDisabled() || this.kjStreaming())
3506
+ return;
3507
+ this.kjSend.emit(text);
3508
+ this.kjValue.set('');
3509
+ this.autogrow();
3510
+ }
3511
+ autogrow() {
3512
+ const el = this.ta().nativeElement;
3513
+ el.style.height = 'auto';
3514
+ el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
3515
+ }
3516
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjPromptInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
3517
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjPromptInput, isStandalone: true, selector: "kj-prompt-input", inputs: { kjValue: { classPropertyName: "kjValue", publicName: "kjValue", isSignal: true, isRequired: false, transformFunction: null }, kjPlaceholder: { classPropertyName: "kjPlaceholder", publicName: "kjPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, kjLabel: { classPropertyName: "kjLabel", publicName: "kjLabel", isSignal: true, isRequired: false, transformFunction: null }, kjStreaming: { classPropertyName: "kjStreaming", publicName: "kjStreaming", isSignal: true, isRequired: false, transformFunction: null }, kjDisabled: { classPropertyName: "kjDisabled", publicName: "kjDisabled", isSignal: true, isRequired: false, transformFunction: null }, kjSlashCommands: { classPropertyName: "kjSlashCommands", publicName: "kjSlashCommands", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { kjValue: "kjValueChange", kjSend: "kjSend", kjStop: "kjStop", kjSlashSelect: "kjSlashSelect" }, host: { classAttribute: "kj-prompt-host" }, viewQueries: [{ propertyName: "ta", first: true, predicate: ["ta"], descendants: true, isSignal: true }], ngImport: i0, template: `
3518
+ <form class="kj-prompt" (submit)="onSubmit($event)">
3519
+ @if (slashOpen()) {
3520
+ <ul class="kj-prompt__slash" role="listbox" [id]="listboxId" aria-label="Slash commands">
3521
+ @for (cmd of slashMatches(); track cmd.name; let i = $index) {
3522
+ <li
3523
+ class="kj-prompt__slash-item"
3524
+ role="option"
3525
+ [id]="optionId(i)"
3526
+ [attr.aria-selected]="i === activeIndex()"
3527
+ [class.is-active]="i === activeIndex()"
3528
+ (mousedown)="pickSlash($event, cmd)"
3529
+ >
3530
+ <span class="kj-prompt__slash-name">{{ cmd.name }}</span>
3531
+ @if (cmd.description) {
3532
+ <span class="kj-prompt__slash-desc">{{ cmd.description }}</span>
3533
+ }
3534
+ </li>
3535
+ }
3536
+ </ul>
3537
+ }
3538
+
3539
+ <label class="kj-visually-hidden" [attr.for]="textareaId">{{ kjLabel() }}</label>
3540
+ <textarea
3541
+ #ta
3542
+ class="kj-prompt__textarea"
3543
+ [id]="textareaId"
3544
+ [attr.placeholder]="kjPlaceholder()"
3545
+ [attr.aria-label]="kjLabel()"
3546
+ [attr.role]="slashOpen() ? 'combobox' : null"
3547
+ [attr.aria-expanded]="slashOpen() ? 'true' : null"
3548
+ [attr.aria-controls]="slashOpen() ? listboxId : null"
3549
+ [attr.aria-activedescendant]="slashOpen() ? optionId(activeIndex()) : null"
3550
+ [attr.aria-haspopup]="slashOpen() ? 'listbox' : null"
3551
+ [attr.aria-autocomplete]="slashOpen() ? 'list' : null"
3552
+ [disabled]="kjDisabled()"
3553
+ [value]="kjValue()"
3554
+ rows="1"
3555
+ (input)="onInput($event)"
3556
+ (keydown)="onKeydown($event)"
3557
+ ></textarea>
3558
+
3559
+ <div class="kj-prompt__actions">
3560
+ <span class="kj-prompt__attachments">
3561
+ <ng-content select="[kjPromptAttachments]" />
3562
+ </span>
3563
+ @if (kjStreaming()) {
3564
+ <button
3565
+ type="button"
3566
+ class="kj-prompt__btn kj-prompt__btn--stop"
3567
+ aria-label="Stop generating"
3568
+ (click)="onStop()"
3569
+ >
3570
+ <span aria-hidden="true">■</span>
3571
+ </button>
3572
+ } @else {
3573
+ <button
3574
+ type="submit"
3575
+ class="kj-prompt__btn kj-prompt__btn--send"
3576
+ aria-label="Send message"
3577
+ [disabled]="kjDisabled() || kjValue().trim().length === 0"
3578
+ >
3579
+ <span aria-hidden="true">↥</span>
3580
+ </button>
3581
+ }
3582
+ </div>
3583
+ </form>
3584
+ `, isInline: true, styles: ["@layer kj.component{.kj-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-chat-thread{display:flex;flex-direction:column;gap:var(--kj-space-md);padding:var(--kj-space-md);background:var(--kj-bg-body);color:var(--kj-fg-default);border-radius:var(--kj-radius-box);overflow-y:auto;font-family:var(--kj-font-sans)}.kj-chat-msg{display:flex;gap:var(--kj-space-sm);align-items:flex-start;max-width:100%}.kj-chat-msg[data-side=end]{flex-direction:row-reverse;margin-inline-start:auto}.kj-chat-msg[data-role=system]{justify-content:center}.kj-chat-msg__avatar{flex:0 0 auto;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;font-size:var(--kj-text-sm);font-weight:600;background:var(--kj-bg-surface);color:var(--kj-fg-default);border:1px solid var(--kj-border-default)}.kj-chat-msg__bubble{display:flex;flex-direction:column;gap:var(--kj-space-xs);padding:var(--kj-space-sm) var(--kj-space-md);border-radius:var(--kj-radius-box);background:var(--kj-bg-surface);color:var(--kj-fg-default);max-width:min(48rem,100%);overflow-wrap:anywhere}.kj-chat-msg[data-role=user] .kj-chat-msg__bubble{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-chat-msg[data-role=system] .kj-chat-msg__bubble{background:transparent;color:var(--kj-fg-muted);font-size:var(--kj-text-sm);text-align:center;padding-block:var(--kj-space-xs)}.kj-chat-msg__body :is(p){margin:0 0 var(--kj-space-xs)}.kj-chat-msg__body :is(p):last-child{margin-bottom:0}.kj-chat-msg__error{margin:0;color:var(--kj-fg-danger);font-size:var(--kj-text-sm)}.kj-md-link{color:inherit;text-decoration:underline}.kj-md-code{font-family:ui-monospace,monospace;background:color-mix(in srgb,currentColor 12%,transparent);padding:.1em .35em;border-radius:var(--kj-radius-field);font-size:.9em}.kj-chat-code{border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);overflow:hidden;margin:var(--kj-space-xs) 0;background:var(--kj-bg-body)}.kj-chat-code__bar{display:flex;align-items:center;justify-content:space-between;padding:.25rem var(--kj-space-sm);background:var(--kj-bg-surface);border-bottom:1px solid var(--kj-border-default);font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-chat-code__copy{min-height:1.75rem;padding:.25rem .6rem;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);color:var(--kj-fg-default);font-size:var(--kj-text-sm);cursor:pointer}.kj-chat-code__copy:hover{background:var(--kj-bg-surface)}.kj-chat-code__copy:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-chat-code__pre{margin:0;padding:var(--kj-space-sm);overflow-x:auto;font-family:ui-monospace,monospace;font-size:.9em;color:var(--kj-fg-default)}.kj-chat-tool{display:flex;align-items:center;gap:var(--kj-space-xs);padding:.35rem var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);font-size:var(--kj-text-sm)}.kj-chat-tool__name{font-weight:600;font-family:ui-monospace,monospace}.kj-chat-tool__status{margin-inline-start:auto;color:var(--kj-fg-muted);text-transform:capitalize}.kj-chat-tool[data-status=error]{border-color:var(--kj-border-danger)}.kj-chat-tool[data-status=error] .kj-chat-tool__status,.kj-chat-tool__error{color:var(--kj-fg-danger)}.kj-chat-cites{list-style:none;margin:var(--kj-space-xs) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--kj-space-xs)}.kj-chat-cite{display:inline-flex;align-items:baseline;gap:.35rem;padding:.15rem .5rem;border:1px solid var(--kj-border-default);border-radius:999px;font-size:var(--kj-text-sm);background:var(--kj-bg-body)}.kj-chat-cite__link{color:var(--kj-fg-info);text-decoration:none}.kj-chat-cite__link:hover{text-decoration:underline}.kj-chat-cite__snippet{color:var(--kj-fg-muted)}.kj-chat-typing{display:inline-flex;gap:.25rem;align-items:center;padding:.25rem 0}.kj-chat-typing__dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--kj-fg-muted);animation:kj-chat-bounce 1.2s infinite ease-in-out both}.kj-chat-typing__dot:nth-child(2){animation-delay:.15s}.kj-chat-typing__dot:nth-child(3){animation-delay:.3s}@keyframes kj-chat-bounce{0%,80%,to{transform:scale(.5);opacity:.4}40%{transform:scale(1);opacity:1}}@media(prefers-reduced-motion:reduce){.kj-chat-typing__dot{animation:none;opacity:.6}}.kj-prompt{position:relative;display:flex;align-items:flex-end;gap:var(--kj-space-sm);padding:var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-box);background:var(--kj-bg-field, var(--kj-input-bg))}.kj-prompt:focus-within{border-color:var(--kj-border-focus)}.kj-prompt__textarea{flex:1 1 auto;resize:none;border:none;outline:none;background:transparent;color:var(--kj-input-fg, var(--kj-fg-default));font-family:var(--kj-font-sans);font-size:var(--kj-input-font-size, 1rem);line-height:1.5;max-height:200px;overflow-y:auto}.kj-prompt__textarea::placeholder{color:var(--kj-input-placeholder-fg, var(--kj-fg-muted))}.kj-prompt__actions{display:flex;align-items:center;gap:var(--kj-space-xs);flex:0 0 auto}.kj-prompt__btn{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;border:none;cursor:pointer;font-size:1.1rem}.kj-prompt__btn:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-prompt__btn--send{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__btn--send:disabled{opacity:.5;cursor:not-allowed}.kj-prompt__btn--stop{background:var(--kj-bg-danger);color:var(--kj-fg-on-danger)}.kj-prompt__slash{position:absolute;bottom:calc(100% + .25rem);left:0;right:0;margin:0;padding:.25rem;list-style:none;background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);box-shadow:0 4px 16px #00000026;max-height:14rem;overflow-y:auto;z-index:10}.kj-prompt__slash-item{display:flex;flex-direction:column;gap:.1rem;padding:var(--kj-space-xs) var(--kj-space-sm);border-radius:var(--kj-radius-field);cursor:pointer}.kj-prompt__slash-item.is-active,.kj-prompt__slash-item:hover{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__slash-name{font-family:ui-monospace,monospace;font-weight:600}.kj-prompt__slash-desc{font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-prompt__slash-item.is-active .kj-prompt__slash-desc,.kj-prompt__slash-item:hover .kj-prompt__slash-desc{color:inherit}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
3585
+ }
3586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjPromptInput, decorators: [{
3587
+ type: Component,
3588
+ args: [{ selector: 'kj-prompt-input', standalone: true, template: `
3589
+ <form class="kj-prompt" (submit)="onSubmit($event)">
3590
+ @if (slashOpen()) {
3591
+ <ul class="kj-prompt__slash" role="listbox" [id]="listboxId" aria-label="Slash commands">
3592
+ @for (cmd of slashMatches(); track cmd.name; let i = $index) {
3593
+ <li
3594
+ class="kj-prompt__slash-item"
3595
+ role="option"
3596
+ [id]="optionId(i)"
3597
+ [attr.aria-selected]="i === activeIndex()"
3598
+ [class.is-active]="i === activeIndex()"
3599
+ (mousedown)="pickSlash($event, cmd)"
3600
+ >
3601
+ <span class="kj-prompt__slash-name">{{ cmd.name }}</span>
3602
+ @if (cmd.description) {
3603
+ <span class="kj-prompt__slash-desc">{{ cmd.description }}</span>
3604
+ }
3605
+ </li>
3606
+ }
3607
+ </ul>
3608
+ }
3609
+
3610
+ <label class="kj-visually-hidden" [attr.for]="textareaId">{{ kjLabel() }}</label>
3611
+ <textarea
3612
+ #ta
3613
+ class="kj-prompt__textarea"
3614
+ [id]="textareaId"
3615
+ [attr.placeholder]="kjPlaceholder()"
3616
+ [attr.aria-label]="kjLabel()"
3617
+ [attr.role]="slashOpen() ? 'combobox' : null"
3618
+ [attr.aria-expanded]="slashOpen() ? 'true' : null"
3619
+ [attr.aria-controls]="slashOpen() ? listboxId : null"
3620
+ [attr.aria-activedescendant]="slashOpen() ? optionId(activeIndex()) : null"
3621
+ [attr.aria-haspopup]="slashOpen() ? 'listbox' : null"
3622
+ [attr.aria-autocomplete]="slashOpen() ? 'list' : null"
3623
+ [disabled]="kjDisabled()"
3624
+ [value]="kjValue()"
3625
+ rows="1"
3626
+ (input)="onInput($event)"
3627
+ (keydown)="onKeydown($event)"
3628
+ ></textarea>
3629
+
3630
+ <div class="kj-prompt__actions">
3631
+ <span class="kj-prompt__attachments">
3632
+ <ng-content select="[kjPromptAttachments]" />
3633
+ </span>
3634
+ @if (kjStreaming()) {
3635
+ <button
3636
+ type="button"
3637
+ class="kj-prompt__btn kj-prompt__btn--stop"
3638
+ aria-label="Stop generating"
3639
+ (click)="onStop()"
3640
+ >
3641
+ <span aria-hidden="true">■</span>
3642
+ </button>
3643
+ } @else {
3644
+ <button
3645
+ type="submit"
3646
+ class="kj-prompt__btn kj-prompt__btn--send"
3647
+ aria-label="Send message"
3648
+ [disabled]="kjDisabled() || kjValue().trim().length === 0"
3649
+ >
3650
+ <span aria-hidden="true">↥</span>
3651
+ </button>
3652
+ }
3653
+ </div>
3654
+ </form>
3655
+ `, encapsulation: ViewEncapsulation.None, host: { class: 'kj-prompt-host' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-chat-thread{display:flex;flex-direction:column;gap:var(--kj-space-md);padding:var(--kj-space-md);background:var(--kj-bg-body);color:var(--kj-fg-default);border-radius:var(--kj-radius-box);overflow-y:auto;font-family:var(--kj-font-sans)}.kj-chat-msg{display:flex;gap:var(--kj-space-sm);align-items:flex-start;max-width:100%}.kj-chat-msg[data-side=end]{flex-direction:row-reverse;margin-inline-start:auto}.kj-chat-msg[data-role=system]{justify-content:center}.kj-chat-msg__avatar{flex:0 0 auto;width:2rem;height:2rem;border-radius:50%;display:grid;place-items:center;font-size:var(--kj-text-sm);font-weight:600;background:var(--kj-bg-surface);color:var(--kj-fg-default);border:1px solid var(--kj-border-default)}.kj-chat-msg__bubble{display:flex;flex-direction:column;gap:var(--kj-space-xs);padding:var(--kj-space-sm) var(--kj-space-md);border-radius:var(--kj-radius-box);background:var(--kj-bg-surface);color:var(--kj-fg-default);max-width:min(48rem,100%);overflow-wrap:anywhere}.kj-chat-msg[data-role=user] .kj-chat-msg__bubble{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-chat-msg[data-role=system] .kj-chat-msg__bubble{background:transparent;color:var(--kj-fg-muted);font-size:var(--kj-text-sm);text-align:center;padding-block:var(--kj-space-xs)}.kj-chat-msg__body :is(p){margin:0 0 var(--kj-space-xs)}.kj-chat-msg__body :is(p):last-child{margin-bottom:0}.kj-chat-msg__error{margin:0;color:var(--kj-fg-danger);font-size:var(--kj-text-sm)}.kj-md-link{color:inherit;text-decoration:underline}.kj-md-code{font-family:ui-monospace,monospace;background:color-mix(in srgb,currentColor 12%,transparent);padding:.1em .35em;border-radius:var(--kj-radius-field);font-size:.9em}.kj-chat-code{border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);overflow:hidden;margin:var(--kj-space-xs) 0;background:var(--kj-bg-body)}.kj-chat-code__bar{display:flex;align-items:center;justify-content:space-between;padding:.25rem var(--kj-space-sm);background:var(--kj-bg-surface);border-bottom:1px solid var(--kj-border-default);font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-chat-code__copy{min-height:1.75rem;padding:.25rem .6rem;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);color:var(--kj-fg-default);font-size:var(--kj-text-sm);cursor:pointer}.kj-chat-code__copy:hover{background:var(--kj-bg-surface)}.kj-chat-code__copy:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-chat-code__pre{margin:0;padding:var(--kj-space-sm);overflow-x:auto;font-family:ui-monospace,monospace;font-size:.9em;color:var(--kj-fg-default)}.kj-chat-tool{display:flex;align-items:center;gap:var(--kj-space-xs);padding:.35rem var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);background:var(--kj-bg-body);font-size:var(--kj-text-sm)}.kj-chat-tool__name{font-weight:600;font-family:ui-monospace,monospace}.kj-chat-tool__status{margin-inline-start:auto;color:var(--kj-fg-muted);text-transform:capitalize}.kj-chat-tool[data-status=error]{border-color:var(--kj-border-danger)}.kj-chat-tool[data-status=error] .kj-chat-tool__status,.kj-chat-tool__error{color:var(--kj-fg-danger)}.kj-chat-cites{list-style:none;margin:var(--kj-space-xs) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--kj-space-xs)}.kj-chat-cite{display:inline-flex;align-items:baseline;gap:.35rem;padding:.15rem .5rem;border:1px solid var(--kj-border-default);border-radius:999px;font-size:var(--kj-text-sm);background:var(--kj-bg-body)}.kj-chat-cite__link{color:var(--kj-fg-info);text-decoration:none}.kj-chat-cite__link:hover{text-decoration:underline}.kj-chat-cite__snippet{color:var(--kj-fg-muted)}.kj-chat-typing{display:inline-flex;gap:.25rem;align-items:center;padding:.25rem 0}.kj-chat-typing__dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--kj-fg-muted);animation:kj-chat-bounce 1.2s infinite ease-in-out both}.kj-chat-typing__dot:nth-child(2){animation-delay:.15s}.kj-chat-typing__dot:nth-child(3){animation-delay:.3s}@keyframes kj-chat-bounce{0%,80%,to{transform:scale(.5);opacity:.4}40%{transform:scale(1);opacity:1}}@media(prefers-reduced-motion:reduce){.kj-chat-typing__dot{animation:none;opacity:.6}}.kj-prompt{position:relative;display:flex;align-items:flex-end;gap:var(--kj-space-sm);padding:var(--kj-space-sm);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-box);background:var(--kj-bg-field, var(--kj-input-bg))}.kj-prompt:focus-within{border-color:var(--kj-border-focus)}.kj-prompt__textarea{flex:1 1 auto;resize:none;border:none;outline:none;background:transparent;color:var(--kj-input-fg, var(--kj-fg-default));font-family:var(--kj-font-sans);font-size:var(--kj-input-font-size, 1rem);line-height:1.5;max-height:200px;overflow-y:auto}.kj-prompt__textarea::placeholder{color:var(--kj-input-placeholder-fg, var(--kj-fg-muted))}.kj-prompt__actions{display:flex;align-items:center;gap:var(--kj-space-xs);flex:0 0 auto}.kj-prompt__btn{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;border:none;cursor:pointer;font-size:1.1rem}.kj-prompt__btn:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:2px}.kj-prompt__btn--send{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__btn--send:disabled{opacity:.5;cursor:not-allowed}.kj-prompt__btn--stop{background:var(--kj-bg-danger);color:var(--kj-fg-on-danger)}.kj-prompt__slash{position:absolute;bottom:calc(100% + .25rem);left:0;right:0;margin:0;padding:.25rem;list-style:none;background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-field);box-shadow:0 4px 16px #00000026;max-height:14rem;overflow-y:auto;z-index:10}.kj-prompt__slash-item{display:flex;flex-direction:column;gap:.1rem;padding:var(--kj-space-xs) var(--kj-space-sm);border-radius:var(--kj-radius-field);cursor:pointer}.kj-prompt__slash-item.is-active,.kj-prompt__slash-item:hover{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary)}.kj-prompt__slash-name{font-family:ui-monospace,monospace;font-weight:600}.kj-prompt__slash-desc{font-size:var(--kj-text-sm);color:var(--kj-fg-muted)}.kj-prompt__slash-item.is-active .kj-prompt__slash-desc,.kj-prompt__slash-item:hover .kj-prompt__slash-desc{color:inherit}}\n"] }]
3656
+ }], ctorParameters: () => [], propDecorators: { kjValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjValue", required: false }] }, { type: i0.Output, args: ["kjValueChange"] }], kjPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjPlaceholder", required: false }] }], kjLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLabel", required: false }] }], kjStreaming: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjStreaming", required: false }] }], kjDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjDisabled", required: false }] }], kjSlashCommands: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSlashCommands", required: false }] }], kjSend: [{ type: i0.Output, args: ["kjSend"] }], kjStop: [{ type: i0.Output, args: ["kjStop"] }], kjSlashSelect: [{ type: i0.Output, args: ["kjSlashSelect"] }], ta: [{ type: i0.ViewChild, args: ['ta', { isSignal: true }] }] } });
3657
+
3658
+ let checkboxIdCounter = 0;
3659
+ /**
3660
+ * Styled wrapper around the headless `KjCheckbox` directive.
3661
+ *
3662
+ * The host renders a `<label>` wrapping the checkbox box and any projected
3663
+ * content (label text). Clicking anywhere on the label checks/unchecks the
3664
+ * box. When `disabled` is set, both the box and label text dim via
3665
+ * `[data-disabled]` on the host.
3666
+ *
3667
+ * @doc-example Default
3668
+ * The default checkbox bound to a `signal<boolean>` via `[(checked)]`.
3669
+ * @doc-file checkbox.default.example.ts
3670
+ * @doc-example Usage
3671
+ * A walkthrough of the most common checkbox usages — checked binding,
3672
+ * indeterminate parent, size variants, and disabled.
3673
+ * @doc-file checkbox.usage.example.ts
3674
+ * @doc-example Checked
3675
+ * Pre-selected on first render. Two-way bind to persist user changes.
3676
+ * @doc-file checkbox.checked.example.ts
3677
+ * @doc-example Indeterminate
3678
+ * Tri-state "some-of-many" parent for a select-all row.
3679
+ * @doc-file checkbox.indeterminate.example.ts
3680
+ * @doc-example Disabled
3681
+ * `[disabled]="true"` dims the box + label and removes pointer events.
3682
+ * @doc-file checkbox.disabled.example.ts
3683
+ *
3684
+ * @doc-keyboard
3685
+ * Space — Toggles the checked state
3686
+ * Tab — Moves focus to the next focusable element
3687
+ *
3688
+ * @doc-aria
3689
+ * role="checkbox" — Applied to the inner focusable box by the headless directive
3690
+ * aria-checked — Reflects `true`, `false`, or `"mixed"` for indeterminate
3691
+ * aria-disabled — Reflected when `[disabled]` is true
3692
+ * aria-labelledby — Auto-wired to the projected label span
3693
+ * data-disabled — Mirrors the disabled posture for theme/scope hooks
3694
+ * data-indeterminate — Reflects the indeterminate posture for the dash glyph
3695
+ *
3696
+ * @doc-css-var
3697
+ * --kj-checkbox-size — Box edge length. `data-size="sm|lg"` overrides; default 1rem.
3698
+ * --kj-checkbox-bg — Unchecked background fill. Defaults to --kj-bg-body.
2592
3699
  * --kj-checkbox-bg-checked — Background when checked or indeterminate. Defaults to --kj-bg-primary.
2593
3700
  * --kj-checkbox-fg-checked — Checkmark/dash color. Defaults to --kj-fg-on-primary.
2594
3701
  * --kj-checkbox-border — Border color when unchecked. Defaults to --kj-border-default.
@@ -3618,6 +4725,124 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
3618
4725
  `, encapsulation: ViewEncapsulation.None, host: { class: 'kj-date-picker-host', style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-date-picker{display:inline-flex;align-items:center;gap:var(--kj-space-xs);position:relative}.kj-date-picker__input{--kj-date-picker-input-height: 2.25rem;appearance:none;border:var(--kj-border) solid var(--kj-border-default);border-radius:var(--kj-radius-field);padding:0 var(--kj-space-md);height:var(--kj-date-picker-input-height);font:inherit;background:var(--kj-bg-field);color:var(--kj-fg-default);min-width:12ch}.kj-date-picker[data-size=xs] .kj-date-picker__input{--kj-date-picker-input-height: 1.75rem;font-size:.75rem;padding-inline:var(--kj-space-sm);min-width:0}.kj-date-picker[data-size=sm] .kj-date-picker__input{--kj-date-picker-input-height: 2rem;font-size:.8125rem}.kj-date-picker[data-size=lg] .kj-date-picker__input{--kj-date-picker-input-height: 2.75rem;font-size:1rem}.kj-date-picker__input:focus{outline:2px solid var(--kj-border-focus);outline-offset:2px;border-color:var(--kj-border-focus)}.kj-date-picker__input[disabled]{opacity:.55;cursor:not-allowed}.kj-date-picker__panel{box-sizing:border-box;z-index:50;display:inline-block;background:var(--kj-bg-elevated);color:var(--kj-fg-default);border:var(--kj-border) solid var(--kj-border-default);border-radius:var(--kj-radius-box);box-shadow:var(--kj-shadow-md);padding:var(--kj-space-sm)}.kj-date-picker__panel .kj-calendar{padding:0}.kj-date-picker__panel[hidden]{display:none}\n"] }]
3619
4726
  }], propDecorators: { kjValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjValue", required: false }] }, { type: i0.Output, args: ["kjValueChange"] }], kjOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjOpen", required: false }] }, { type: i0.Output, args: ["kjOpenChange"] }], kjMin: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjMin", required: false }] }], kjMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjMax", required: false }] }], kjDisabledDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjDisabledDates", required: false }] }], kjLocale: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLocale", required: false }] }], kjFirstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjFirstDayOfWeek", required: false }] }], kjPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjPlaceholder", required: false }] }], kjReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjReadonly", required: false }] }], kjDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjDisabled", required: false }] }], kjSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSize", required: false }] }] } });
3620
4727
 
4728
+ /**
4729
+ * Styled Date Range Presets — a compact, keyboard-navigable list of named
4730
+ * quick-selects ("Today", "Last 7 days", "This quarter", …). Picking one
4731
+ * resolves its inclusive `{ start, end }` range and commits the two-way
4732
+ * `kjValue`.
4733
+ *
4734
+ * Built as the reusable presets primitive from the date/time roadmap slice:
4735
+ * it slots beside a range calendar, but works standalone against any
4736
+ * `signal<KjDateRange | null>`.
4737
+ *
4738
+ * **Accessibility (WCAG 2.1 AAA):**
4739
+ * - the list is `role="listbox"` with an accessible name; each preset is a
4740
+ * `role="option"` `<button>` carrying `aria-selected`.
4741
+ * - roving tabindex — one tab stop; Up/Down (and Home/End) move between
4742
+ * options; Enter / Space select (native button activation).
4743
+ * - the selected preset is conveyed by `aria-selected`, not color alone.
4744
+ *
4745
+ * @doc-example Default
4746
+ * The ten built-in presets bound to a `signal<KjDateRange | null>`.
4747
+ * @doc-file date-range-presets.example.ts
4748
+ * @doc-example Custom presets
4749
+ * Spread `defaultDateRangePresets()` and append your own `getRange`.
4750
+ * @doc-file date-range-presets.custom.example.ts
4751
+ *
4752
+ * @doc-keyboard
4753
+ * ArrowDown|ArrowUp — Moves between presets
4754
+ * Home|End — Jumps to the first / last preset
4755
+ * Enter|Space — Selects the focused preset
4756
+ *
4757
+ * @doc-aria
4758
+ * role="listbox" — On the container; `aria-orientation="vertical"`
4759
+ * aria-label — Names the list ("Date range presets" by default)
4760
+ * role="option" — On each preset button
4761
+ * aria-selected — Reflects the chosen preset
4762
+ *
4763
+ * @doc-css-var
4764
+ * --kj-date-range-presets-min-width — Min width of the list. Default 12rem.
4765
+ *
4766
+ * @doc-touch
4767
+ * Preset rows are 44px tall to meet the WCAG 2.5.5 target size.
4768
+ *
4769
+ * @doc-related date-picker,calendar
4770
+ *
4771
+ * @doc-category Library/Data input
4772
+ * @doc
4773
+ * @doc-name date-range-presets
4774
+ * @doc-description Themed listbox of date-range quick-selects that resolve to an inclusive start/end range.
4775
+ * @doc-is-main
4776
+ */
4777
+ class KjDateRangePresetsComponent {
4778
+ /** Selected range. Two-way bindable — `[(kjValue)]`. `null` clears. */
4779
+ kjValue = model(null, /* @ts-ignore */
4780
+ ...(ngDevMode ? [{ debugName: "kjValue" }] : /* istanbul ignore next */ []));
4781
+ /** Presets to render. Defaults to the ten built-ins. */
4782
+ kjPresets = input(defaultDateRangePresets(), /* @ts-ignore */
4783
+ ...(ngDevMode ? [{ debugName: "kjPresets" }] : /* istanbul ignore next */ []));
4784
+ /** Accessible name for the list. */
4785
+ kjLabel = input('Date range presets', /* @ts-ignore */
4786
+ ...(ngDevMode ? [{ debugName: "kjLabel" }] : /* istanbul ignore next */ []));
4787
+ /** Injectable "now" for the preset math. Defaults to the current instant. */
4788
+ kjNow = input(null, /* @ts-ignore */
4789
+ ...(ngDevMode ? [{ debugName: "kjNow" }] : /* istanbul ignore next */ []));
4790
+ /** Disable the whole list. */
4791
+ kjDisabled = input(false, { ...(ngDevMode ? { debugName: "kjDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4792
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDateRangePresetsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4793
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjDateRangePresetsComponent, isStandalone: true, selector: "kj-date-range-presets", inputs: { kjValue: { classPropertyName: "kjValue", publicName: "kjValue", isSignal: true, isRequired: false, transformFunction: null }, kjPresets: { classPropertyName: "kjPresets", publicName: "kjPresets", isSignal: true, isRequired: false, transformFunction: null }, kjLabel: { classPropertyName: "kjLabel", publicName: "kjLabel", isSignal: true, isRequired: false, transformFunction: null }, kjNow: { classPropertyName: "kjNow", publicName: "kjNow", isSignal: true, isRequired: false, transformFunction: null }, kjDisabled: { classPropertyName: "kjDisabled", publicName: "kjDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { kjValue: "kjValueChange" }, host: { styleAttribute: "display: contents;", classAttribute: "kj-date-range-presets-host" }, ngImport: i0, template: `
4794
+ <div
4795
+ kjDateRangePresets
4796
+ class="kj-date-range-presets"
4797
+ [kjValue]="kjValue() ?? null!"
4798
+ (kjValueChange)="kjValue.set($event)"
4799
+ [kjPresets]="kjPresets()"
4800
+ [kjLabel]="kjLabel()"
4801
+ [kjNow]="kjNow() ?? null!"
4802
+ [kjDisabled]="kjDisabled()"
4803
+ >
4804
+ @for (preset of kjPresets(); track preset.id) {
4805
+ <button
4806
+ kjDateRangePresetOption
4807
+ #opt="kjDateRangePresetOption"
4808
+ class="kj-date-range-presets__option"
4809
+ [kjPreset]="preset"
4810
+ [attr.data-selected]="opt.selected() ? '' : null"
4811
+ >
4812
+ {{ preset.label }}
4813
+ </button>
4814
+ }
4815
+ </div>
4816
+ `, isInline: true, styles: [".kj-date-range-presets{display:flex;flex-direction:column;gap:2px;min-width:var(--kj-date-range-presets-min-width, 12rem);padding:var(--kj-space-xs, .25rem);background:var(--kj-bg-elevated, transparent);border:var(--kj-border) solid var(--kj-border-subtle, transparent);border-radius:var(--kj-radius-field, .375rem);font-family:inherit;font-size:.8125rem;color:var(--kj-fg-default)}.kj-date-range-presets__option{appearance:none;display:flex;align-items:center;min-height:44px;padding:0 var(--kj-space-md, .75rem);background:transparent;border:var(--kj-border) solid transparent;border-radius:var(--kj-radius-field, .375rem);color:inherit;font:inherit;text-align:start;cursor:pointer}.kj-date-range-presets__option:hover:not([disabled]){background:var(--kj-bg-field)}.kj-date-range-presets__option:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:-2px}.kj-date-range-presets__option[data-selected]{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary);font-weight:600}.kj-date-range-presets__option[disabled]{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: KjDateRangePresets, selector: "[kjDateRangePresets]", inputs: ["kjValue", "kjPresets", "kjLabel", "kjNow", "kjReadonly"], outputs: ["kjValueChange"], exportAs: ["kjDateRangePresets"] }, { kind: "directive", type: KjDateRangePresetOption, selector: "button[kjDateRangePresetOption]", inputs: ["kjPreset"], exportAs: ["kjDateRangePresetOption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4817
+ }
4818
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDateRangePresetsComponent, decorators: [{
4819
+ type: Component,
4820
+ args: [{ selector: 'kj-date-range-presets', standalone: true, imports: [KjDateRangePresets, KjDateRangePresetOption], template: `
4821
+ <div
4822
+ kjDateRangePresets
4823
+ class="kj-date-range-presets"
4824
+ [kjValue]="kjValue() ?? null!"
4825
+ (kjValueChange)="kjValue.set($event)"
4826
+ [kjPresets]="kjPresets()"
4827
+ [kjLabel]="kjLabel()"
4828
+ [kjNow]="kjNow() ?? null!"
4829
+ [kjDisabled]="kjDisabled()"
4830
+ >
4831
+ @for (preset of kjPresets(); track preset.id) {
4832
+ <button
4833
+ kjDateRangePresetOption
4834
+ #opt="kjDateRangePresetOption"
4835
+ class="kj-date-range-presets__option"
4836
+ [kjPreset]="preset"
4837
+ [attr.data-selected]="opt.selected() ? '' : null"
4838
+ >
4839
+ {{ preset.label }}
4840
+ </button>
4841
+ }
4842
+ </div>
4843
+ `, encapsulation: ViewEncapsulation.None, host: { class: 'kj-date-range-presets-host', style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-date-range-presets{display:flex;flex-direction:column;gap:2px;min-width:var(--kj-date-range-presets-min-width, 12rem);padding:var(--kj-space-xs, .25rem);background:var(--kj-bg-elevated, transparent);border:var(--kj-border) solid var(--kj-border-subtle, transparent);border-radius:var(--kj-radius-field, .375rem);font-family:inherit;font-size:.8125rem;color:var(--kj-fg-default)}.kj-date-range-presets__option{appearance:none;display:flex;align-items:center;min-height:44px;padding:0 var(--kj-space-md, .75rem);background:transparent;border:var(--kj-border) solid transparent;border-radius:var(--kj-radius-field, .375rem);color:inherit;font:inherit;text-align:start;cursor:pointer}.kj-date-range-presets__option:hover:not([disabled]){background:var(--kj-bg-field)}.kj-date-range-presets__option:focus-visible{outline:2px solid var(--kj-border-focus);outline-offset:-2px}.kj-date-range-presets__option[data-selected]{background:var(--kj-bg-primary);color:var(--kj-fg-on-primary);font-weight:600}.kj-date-range-presets__option[disabled]{opacity:.4;cursor:not-allowed}\n"] }]
4844
+ }], propDecorators: { kjValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjValue", required: false }] }, { type: i0.Output, args: ["kjValueChange"] }], kjPresets: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjPresets", required: false }] }], kjLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLabel", required: false }] }], kjNow: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjNow", required: false }] }], kjDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjDisabled", required: false }] }] } });
4845
+
3621
4846
  /** Format a Date as a locale short date + HH:mm time. */
3622
4847
  function formatDateTime(d, locale) {
3623
4848
  const date = new Intl.DateTimeFormat(locale || undefined, { dateStyle: 'short' }).format(d);
@@ -3893,6 +5118,108 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
3893
5118
  args: [{ selector: 'kj-dialog-shell', standalone: true, template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-dialog-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.kj-dialog{display:flex;flex-direction:column;background:var(--kj-bg-elevated);color:var(--kj-fg-default);border-radius:var(--kj-radius-box);box-shadow:var(--kj-shadow-lg);min-width:24rem;max-width:min(40rem,calc(100vw - 2rem));max-height:calc(100vh - 4rem);overflow:hidden;padding:var(--kj-space-xl)}.kj-dialog-header{display:flex;align-items:center;justify-content:flex-start;padding:var(--kj-space-lg) var(--kj-space-xl);border-bottom:var(--kj-border) solid var(--kj-border-muted)}.kj-dialog-header[data-align=center]{justify-content:center}.kj-dialog-title{display:block;margin:0;font:600 1.125rem / 1.3 var(--kj-font-sans);color:var(--kj-fg-default)}.kj-dialog-body{flex:1;color:var(--kj-fg-default);font:.9375rem / 1.5 var(--kj-font-sans)}.kj-dialog-body[data-padded]{padding:var(--kj-space-lg) var(--kj-space-xl)}.kj-dialog-body[data-scroll]{overflow-y:auto}.kj-dialog-footer{display:flex;align-items:center;gap:var(--kj-space-sm);padding:var(--kj-space-lg) var(--kj-space-xl);border-top:var(--kj-border) solid var(--kj-border-muted)}.kj-dialog-footer[data-align=start]{justify-content:flex-start}.kj-dialog-footer[data-align=center]{justify-content:center}.kj-dialog-footer[data-align=end]{justify-content:flex-end}.kj-dialog-footer[data-align=between]{justify-content:space-between}}\n"] }]
3894
5119
  }] });
3895
5120
 
5121
+ /**
5122
+ * A visible, keyboard-native control that flips the application's logical text
5123
+ * direction between `ltr` and `rtl`.
5124
+ *
5125
+ * It is the concrete UI the locale provider pointed at: it reads
5126
+ * `KjLocale.isRtl()` and calls `KjLocale.setDirection(...)`. Paired with
5127
+ * `provideKjDocumentDirection()`, one click mirrors the whole page —
5128
+ * `<html dir>` flips and every logical-property layout follows.
5129
+ *
5130
+ * Renders a real `<button type="button">` so it is reachable by Tab and
5131
+ * operable with Enter / Space for free. `aria-pressed` reflects the RTL state
5132
+ * (pressed = RTL), and an accessible name is always present via
5133
+ * `[kjAriaLabel]`. Project custom content to replace the default `LTR` / `RTL`
5134
+ * text label.
5135
+ *
5136
+ * @example
5137
+ * ```html
5138
+ * <kj-direction-toggle />
5139
+ * <kj-direction-toggle kjAriaLabel="Toggle Arabic layout">اتجاه</kj-direction-toggle>
5140
+ * ```
5141
+ *
5142
+ * @doc-example Default
5143
+ * The toggle wired to `KjLocale` — click to flip `<html dir>` and mirror the page.
5144
+ * @doc-file direction-toggle.example.ts
5145
+ *
5146
+ * @doc-keyboard
5147
+ * Enter — Toggles the direction (native button activation)
5148
+ * Space — Toggles the direction (native button activation)
5149
+ * Tab — Moves focus to / from the toggle
5150
+ *
5151
+ * @doc-aria
5152
+ * aria-pressed — Reflects the RTL state (true when direction is rtl)
5153
+ * aria-label — Accessible name; defaults to "Toggle right-to-left layout"
5154
+ * data-direction — Mirrors the resolved direction (ltr | rtl) for theme CSS
5155
+ *
5156
+ * @doc-touch
5157
+ * The button reserves a 44×44px hit area (WCAG 2.5.5) regardless of label size.
5158
+ *
5159
+ * @doc-a11y
5160
+ * A native `<button>` with `aria-pressed` — AT announces "toggle button,
5161
+ * pressed/not pressed". Because mirroring is CSS-logical only, DOM and tab
5162
+ * order are unchanged in both directions (WCAG 1.3.2).
5163
+ *
5164
+ * @doc-related locale
5165
+ *
5166
+ * @doc-css-var
5167
+ * --kj-direction-toggle-bg — Background at rest.
5168
+ * --kj-direction-toggle-fg — Text color.
5169
+ * --kj-direction-toggle-border-color — Border color.
5170
+ * --kj-direction-toggle-radius — Corner radius.
5171
+ * --kj-direction-toggle-padding-x — Inline padding.
5172
+ * --kj-direction-toggle-padding-y — Block padding.
5173
+ *
5174
+ * @doc-category Library/Navigation
5175
+ * @doc
5176
+ * @doc-name direction-toggle
5177
+ * @doc-description Accessible LTR/RTL toggle button that drives KjLocale.direction and mirrors the page.
5178
+ * @doc-is-main
5179
+ */
5180
+ class KjDirectionToggle {
5181
+ locale = inject(KjLocale);
5182
+ /** Resolved logical direction from the shared `KjLocale`. */
5183
+ direction = this.locale.direction;
5184
+ /** `true` when the resolved direction is `rtl`. Drives `aria-pressed`. */
5185
+ isRtl = this.locale.isRtl;
5186
+ /** Accessible name for the toggle button. */
5187
+ kjAriaLabel = input('Toggle right-to-left layout', /* @ts-ignore */
5188
+ ...(ngDevMode ? [{ debugName: "kjAriaLabel" }] : /* istanbul ignore next */ []));
5189
+ /** Flip the direction: `ltr` ⇄ `rtl`. */
5190
+ toggle() {
5191
+ this.locale.setDirection(this.locale.isRtl() ? 'ltr' : 'rtl');
5192
+ }
5193
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDirectionToggle, deps: [], target: i0.ɵɵFactoryTarget.Component });
5194
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: KjDirectionToggle, isStandalone: true, selector: "kj-direction-toggle", inputs: { kjAriaLabel: { classPropertyName: "kjAriaLabel", publicName: "kjAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `
5195
+ <button
5196
+ type="button"
5197
+ class="kj-direction-toggle"
5198
+ [attr.aria-pressed]="isRtl()"
5199
+ [attr.aria-label]="kjAriaLabel()"
5200
+ [attr.data-direction]="direction()"
5201
+ (click)="toggle()"
5202
+ >
5203
+ <ng-content>{{ isRtl() ? 'RTL' : 'LTR' }}</ng-content>
5204
+ </button>
5205
+ `, isInline: true, styles: ["@layer kj.component{.kj-direction-toggle{--kj-direction-toggle-bg: var(--kj-bg-subtle, transparent);--kj-direction-toggle-fg: var(--kj-fg, currentColor);--kj-direction-toggle-border-color: var(--kj-border-color, currentColor);--kj-direction-toggle-radius: var(--kj-radius-field, .5rem);--kj-direction-toggle-padding-x: var(--kj-space-md, .75rem);--kj-direction-toggle-padding-y: var(--kj-space-sm, .5rem);display:inline-flex;align-items:center;justify-content:center;gap:var(--kj-space-xs, .25rem);min-width:44px;min-height:44px;padding-block:var(--kj-direction-toggle-padding-y);padding-inline:var(--kj-direction-toggle-padding-x);background:var(--kj-direction-toggle-bg);color:var(--kj-direction-toggle-fg);border:var(--kj-border, 1px) solid var(--kj-direction-toggle-border-color);border-radius:var(--kj-direction-toggle-radius);font:inherit;font-size:var(--kj-text-sm, .875rem);line-height:1;cursor:pointer;-webkit-user-select:none;user-select:none}.kj-direction-toggle:hover{background:var(--kj-bg-subtle-hover, var(--kj-direction-toggle-bg))}.kj-direction-toggle:focus-visible{outline:var(--kj-focus-ring-width, 2px) solid var(--kj-focus-ring-color, currentColor);outline-offset:2px}.kj-direction-toggle[aria-pressed=true]{background:var(--kj-bg-primary, var(--kj-direction-toggle-bg));color:var(--kj-fg-on-primary, var(--kj-direction-toggle-fg));border-color:var(--kj-bg-primary, var(--kj-direction-toggle-border-color))}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5206
+ }
5207
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDirectionToggle, decorators: [{
5208
+ type: Component,
5209
+ args: [{ selector: 'kj-direction-toggle', standalone: true, template: `
5210
+ <button
5211
+ type="button"
5212
+ class="kj-direction-toggle"
5213
+ [attr.aria-pressed]="isRtl()"
5214
+ [attr.aria-label]="kjAriaLabel()"
5215
+ [attr.data-direction]="direction()"
5216
+ (click)="toggle()"
5217
+ >
5218
+ <ng-content>{{ isRtl() ? 'RTL' : 'LTR' }}</ng-content>
5219
+ </button>
5220
+ `, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-direction-toggle{--kj-direction-toggle-bg: var(--kj-bg-subtle, transparent);--kj-direction-toggle-fg: var(--kj-fg, currentColor);--kj-direction-toggle-border-color: var(--kj-border-color, currentColor);--kj-direction-toggle-radius: var(--kj-radius-field, .5rem);--kj-direction-toggle-padding-x: var(--kj-space-md, .75rem);--kj-direction-toggle-padding-y: var(--kj-space-sm, .5rem);display:inline-flex;align-items:center;justify-content:center;gap:var(--kj-space-xs, .25rem);min-width:44px;min-height:44px;padding-block:var(--kj-direction-toggle-padding-y);padding-inline:var(--kj-direction-toggle-padding-x);background:var(--kj-direction-toggle-bg);color:var(--kj-direction-toggle-fg);border:var(--kj-border, 1px) solid var(--kj-direction-toggle-border-color);border-radius:var(--kj-direction-toggle-radius);font:inherit;font-size:var(--kj-text-sm, .875rem);line-height:1;cursor:pointer;-webkit-user-select:none;user-select:none}.kj-direction-toggle:hover{background:var(--kj-bg-subtle-hover, var(--kj-direction-toggle-bg))}.kj-direction-toggle:focus-visible{outline:var(--kj-focus-ring-width, 2px) solid var(--kj-focus-ring-color, currentColor);outline-offset:2px}.kj-direction-toggle[aria-pressed=true]{background:var(--kj-bg-primary, var(--kj-direction-toggle-bg));color:var(--kj-fg-on-primary, var(--kj-direction-toggle-fg));border-color:var(--kj-bg-primary, var(--kj-direction-toggle-border-color))}}\n"] }]
5221
+ }], propDecorators: { kjAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaLabel", required: false }] }] } });
5222
+
3896
5223
  /**
3897
5224
  * Service-launched drawer (edge-anchored panel). Inject `KjDrawerService` and
3898
5225
  * call `open()` with a template; the drawer absorbs the bottom-sheet pattern
@@ -4048,23 +5375,412 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
4048
5375
  * `[kjDisabled]="true"` keeps the item focusable but blocks activation.
4049
5376
  * @doc-file dropdown-menu.disabled.example.ts
4050
5377
  *
4051
- * @doc-category Library/Overlay
5378
+ * @doc-category Library/Overlay
5379
+ */
5380
+ class KjDropdownMenuComponent {
5381
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDropdownMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5382
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjDropdownMenuComponent, isStandalone: true, selector: "kj-dropdown-menu", host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-dropdown-menu{--kj-dropdown-menu-bg: var(--kj-bg-elevated);--kj-dropdown-menu-fg: var(--kj-fg-default);--kj-dropdown-menu-border-color: var(--kj-border-default);--kj-dropdown-menu-radius: var(--kj-radius-box);--kj-dropdown-menu-padding: var(--kj-space-xs);--kj-dropdown-menu-shadow: var(--kj-shadow-md);display:flex;flex-direction:column;box-sizing:border-box;min-width:12rem;max-width:min(20rem,calc(100vw - 2rem));background:var(--kj-dropdown-menu-bg);color:var(--kj-dropdown-menu-fg);border:var(--kj-border) solid var(--kj-dropdown-menu-border-color);border-radius:var(--kj-dropdown-menu-radius);padding:var(--kj-dropdown-menu-padding);font:.875rem / 1.5 var(--kj-font-sans);box-shadow:var(--kj-dropdown-menu-shadow);pointer-events:auto;z-index:1000}.kj-dropdown-menu[hidden]{display:none}.kj-dropdown-menu-item{--kj-dropdown-menu-item-padding-x: var(--kj-space-md);--kj-dropdown-menu-item-padding-y: var(--kj-space-sm);--kj-dropdown-menu-item-min-height: 2.75rem;--kj-dropdown-menu-item-radius: var(--kj-radius-field);--kj-dropdown-menu-item-hover-bg: var(--kj-bg-surface);--kj-dropdown-menu-item-active-bg: var(--kj-bg-field);display:flex;align-items:center;justify-content:flex-start;gap:var(--kj-space-sm);width:100%;min-height:var(--kj-dropdown-menu-item-min-height);box-sizing:border-box;padding:var(--kj-dropdown-menu-item-padding-y) var(--kj-dropdown-menu-item-padding-x);margin:0;background:transparent;color:inherit;border:none;border-radius:var(--kj-dropdown-menu-item-radius);font:inherit;text-align:start;cursor:pointer;-webkit-user-select:none;user-select:none}.kj-dropdown-menu-item:hover:not([data-disabled]){background:var(--kj-dropdown-menu-item-hover-bg)}.kj-dropdown-menu-item:focus-visible{outline:2px solid var(--kj-bg-primary);outline-offset:-2px}.kj-dropdown-menu-item[aria-current=true]{background:var(--kj-dropdown-menu-item-current-bg, var(--kj-bg-field));color:var(--kj-dropdown-menu-item-current-fg, var(--kj-fg-primary));font-weight:500}.kj-dropdown-menu-item[data-disabled]{cursor:not-allowed;opacity:.5}.kj-dropdown-menu-separator{display:block;height:1px;margin:var(--kj-space-xs) calc(var(--kj-space-xs) * -1);background:color-mix(in oklab,var(--kj-fg-default) 12%,transparent);border:0}.kj-dropdown-menu-label{display:block;padding:var(--kj-space-xs) var(--kj-space-md);font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--kj-fg-default);opacity:.65}.kj-dropdown-menu-group{display:flex;flex-direction:column}@media(prefers-reduced-motion:no-preference){.kj-dropdown-menu{transition:opacity .12s ease-out,transform .12s ease-out}.kj-dropdown-menu[data-state=closed]{opacity:0;transform:scale(.98)}.kj-dropdown-menu[data-state=open]{opacity:1;transform:scale(1)}}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5383
+ }
5384
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDropdownMenuComponent, decorators: [{
5385
+ type: Component,
5386
+ args: [{ selector: 'kj-dropdown-menu', standalone: true, imports: [
5387
+ KjDropdownMenuTrigger,
5388
+ KjDropdownMenuContent,
5389
+ KjDropdownMenuItem,
5390
+ KjDropdownMenuSeparator,
5391
+ KjDropdownMenuLabel,
5392
+ KjDropdownMenuGroup,
5393
+ ], template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-dropdown-menu{--kj-dropdown-menu-bg: var(--kj-bg-elevated);--kj-dropdown-menu-fg: var(--kj-fg-default);--kj-dropdown-menu-border-color: var(--kj-border-default);--kj-dropdown-menu-radius: var(--kj-radius-box);--kj-dropdown-menu-padding: var(--kj-space-xs);--kj-dropdown-menu-shadow: var(--kj-shadow-md);display:flex;flex-direction:column;box-sizing:border-box;min-width:12rem;max-width:min(20rem,calc(100vw - 2rem));background:var(--kj-dropdown-menu-bg);color:var(--kj-dropdown-menu-fg);border:var(--kj-border) solid var(--kj-dropdown-menu-border-color);border-radius:var(--kj-dropdown-menu-radius);padding:var(--kj-dropdown-menu-padding);font:.875rem / 1.5 var(--kj-font-sans);box-shadow:var(--kj-dropdown-menu-shadow);pointer-events:auto;z-index:1000}.kj-dropdown-menu[hidden]{display:none}.kj-dropdown-menu-item{--kj-dropdown-menu-item-padding-x: var(--kj-space-md);--kj-dropdown-menu-item-padding-y: var(--kj-space-sm);--kj-dropdown-menu-item-min-height: 2.75rem;--kj-dropdown-menu-item-radius: var(--kj-radius-field);--kj-dropdown-menu-item-hover-bg: var(--kj-bg-surface);--kj-dropdown-menu-item-active-bg: var(--kj-bg-field);display:flex;align-items:center;justify-content:flex-start;gap:var(--kj-space-sm);width:100%;min-height:var(--kj-dropdown-menu-item-min-height);box-sizing:border-box;padding:var(--kj-dropdown-menu-item-padding-y) var(--kj-dropdown-menu-item-padding-x);margin:0;background:transparent;color:inherit;border:none;border-radius:var(--kj-dropdown-menu-item-radius);font:inherit;text-align:start;cursor:pointer;-webkit-user-select:none;user-select:none}.kj-dropdown-menu-item:hover:not([data-disabled]){background:var(--kj-dropdown-menu-item-hover-bg)}.kj-dropdown-menu-item:focus-visible{outline:2px solid var(--kj-bg-primary);outline-offset:-2px}.kj-dropdown-menu-item[aria-current=true]{background:var(--kj-dropdown-menu-item-current-bg, var(--kj-bg-field));color:var(--kj-dropdown-menu-item-current-fg, var(--kj-fg-primary));font-weight:500}.kj-dropdown-menu-item[data-disabled]{cursor:not-allowed;opacity:.5}.kj-dropdown-menu-separator{display:block;height:1px;margin:var(--kj-space-xs) calc(var(--kj-space-xs) * -1);background:color-mix(in oklab,var(--kj-fg-default) 12%,transparent);border:0}.kj-dropdown-menu-label{display:block;padding:var(--kj-space-xs) var(--kj-space-md);font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--kj-fg-default);opacity:.65}.kj-dropdown-menu-group{display:flex;flex-direction:column}@media(prefers-reduced-motion:no-preference){.kj-dropdown-menu{transition:opacity .12s ease-out,transform .12s ease-out}.kj-dropdown-menu[data-state=closed]{opacity:0;transform:scale(.98)}.kj-dropdown-menu[data-state=open]{opacity:1;transform:scale(1)}}}\n"] }]
5394
+ }] });
5395
+
5396
+ /**
5397
+ * Styled wrapper around the headless `KjSpinner` directive.
5398
+ *
5399
+ * Composes `KjSpinner` via `hostDirectives` so the wrapper's host element is
5400
+ * *the* spinner — `role="status"`, `aria-live="polite"`, `aria-atomic="true"`,
5401
+ * the `aria-label` default ("Loading"), `data-animation`, and
5402
+ * `data-reduced-motion` all land on `<kj-spinner>` itself. `kjVariant` and
5403
+ * `kjSize` are wrapper-level inputs that the host mirrors to `data-variant` /
5404
+ * `data-size` (the directive's own nested `KjVariant` / `KjSize` host
5405
+ * directives are not transitively exposed through outer composition, so the
5406
+ * wrapper takes over the data-attribute reflection at this layer).
5407
+ *
5408
+ * The template renders an `aria-hidden` glyph element (the visual shape that
5409
+ * theme CSS keyframes drive per `data-animation`) and, when no
5410
+ * `aria-labelledby` was authored on the host, a `kjVisuallyHidden` label so
5411
+ * AT always finds an accessible name.
5412
+ *
5413
+ * **Indeterminate-only.** The spinner answers "something is happening" — it
5414
+ * has no value model. For "x of y" use Progress Bar; for missing-content
5415
+ * placeholders use Skeleton.
5416
+ *
5417
+ * @example
5418
+ * ```html
5419
+ * <kj-spinner />
5420
+ * <kj-spinner kjVariant="primary" kjSize="lg" kjAnimation="dots" kjAriaLabel="Sending" />
5421
+ * ```
5422
+ * @doc-example Default
5423
+ * The default playground — `spin` animation, `md` size, neutral variant,
5424
+ * default `aria-label="Loading"`.
5425
+ * @doc-file spinner.example.ts
5426
+ * @doc-example Usage
5427
+ * A walkthrough of the most common spinner usages — size, variant,
5428
+ * animation glyph, and inline placement next to copy.
5429
+ * @doc-file spinner.usage.example.ts
5430
+ * @doc-example Sizes
5431
+ * `xs` / `sm` / `md` / `lg` presets. There is intentionally no `xl` — that
5432
+ * size almost always wants a determinate Progress Bar instead.
5433
+ * @doc-file spinner.sizes.example.ts
5434
+ * @doc-example Variants
5435
+ * `neutral` (inherits `currentColor`), `primary`, `success`, `warning`,
5436
+ * `error`, `info`.
5437
+ * @doc-file spinner.variants.example.ts
5438
+ * @doc-example Animations
5439
+ * Animation shape preset — `spin`, `dots`, `bars`, etc. Themes own the
5440
+ * keyframes per value.
5441
+ * @doc-file spinner.animations.example.ts
5442
+ * @doc-example Inside a button
5443
+ * Embed the spinner inline next to a label to communicate in-flight work.
5444
+ * @doc-file spinner.in-button.example.ts
5445
+ *
5446
+ * @doc-keyboard
5447
+ * — — Non-interactive. The spinner is purely a status indicator.
5448
+ *
5449
+ * @doc-aria
5450
+ * role="status" — set on the host so AT announces it as a live status region
5451
+ * aria-live — "polite" so the label is read without interrupting the user
5452
+ * aria-atomic — "true" so the full label is announced on change
5453
+ * aria-label — Defaults to "Loading"; override per context (e.g. "Sending")
5454
+ * data-animation — Mirrors the resolved animation for theme hooks
5455
+ * data-variant — Mirrors the resolved variant for theme hooks
5456
+ * data-size — Mirrors the resolved size for theme hooks
5457
+ *
5458
+ * @doc-touch
5459
+ * — — Non-interactive; no touch target required.
5460
+ *
5461
+ * @doc-a11y
5462
+ * Indeterminate-only — answers "something is happening", with no value model.
5463
+ * Honours `prefers-reduced-motion` via `data-reduced-motion` on the host, so
5464
+ * themes can swap a calmer animation. When the consumer authors
5465
+ * `aria-labelledby` on the host the wrapper skips the visually-hidden label
5466
+ * to avoid double-naming.
5467
+ *
5468
+ * @doc-related progress-bar,skeleton,toast
5469
+ *
5470
+ * @doc-css-var
5471
+ * --kj-spinner-size — Glyph diameter. Sizes (xs/sm/md/lg) override.
5472
+ * --kj-spinner-color — Foreground color of the glyph. Variants set this; neutral inherits currentColor.
5473
+ * --kj-spinner-track — Track/background color for the spin arc.
5474
+ * --kj-spinner-duration — Base animation duration. Other animations scale off this.
5475
+ *
5476
+ * @doc-category Library/Feedback
5477
+ * @doc
5478
+ * @doc-name spinner
5479
+ * @doc-description Themed indeterminate loading spinner with variant, size, and animation glyph options.
5480
+ * @doc-is-main
5481
+ */
5482
+ class KjSpinnerComponent {
5483
+ /**
5484
+ * Color preset reflected to `data-variant` on the host. Defaults to
5485
+ * `'neutral'`, which resolves to `currentColor` in shipped themes — so a
5486
+ * spinner inside a coloured surface inherits its parent's text colour.
5487
+ */
5488
+ kjVariant = input('neutral', /* @ts-ignore */
5489
+ ...(ngDevMode ? [{ debugName: "kjVariant" }] : /* istanbul ignore next */ []));
5490
+ /**
5491
+ * Size preset reflected to `data-size` on the host. Defaults to `'md'`.
5492
+ * Sizes ship as `xs | sm | md | lg`; an `xl` is intentionally absent — a
5493
+ * spinner that big almost always wants a determinate Progress Bar instead.
5494
+ */
5495
+ kjSize = input('md', /* @ts-ignore */
5496
+ ...(ngDevMode ? [{ debugName: "kjSize" }] : /* istanbul ignore next */ []));
5497
+ /**
5498
+ * Animation shape preset forwarded to `KjSpinner.kjAnimation` via the
5499
+ * composed host directive. Reflects on the host as `data-animation`.
5500
+ * Themes own the keyframes per value.
5501
+ */
5502
+ kjAnimation = input('spin', /* @ts-ignore */
5503
+ ...(ngDevMode ? [{ debugName: "kjAnimation" }] : /* istanbul ignore next */ []));
5504
+ /**
5505
+ * Accessible name forwarded to `KjSpinner.kjAriaLabel` via the composed
5506
+ * host directive. Default `'Loading'`. Used both as the host's
5507
+ * `aria-label` and as the visually-hidden text rendered inside the
5508
+ * wrapper when no consumer-authored `aria-labelledby` is on the element.
5509
+ */
5510
+ kjAriaLabel = input('Loading', /* @ts-ignore */
5511
+ ...(ngDevMode ? [{ debugName: "kjAriaLabel" }] : /* istanbul ignore next */ []));
5512
+ el = inject(ElementRef);
5513
+ /**
5514
+ * Snapshotted at construction: did the consumer author `aria-labelledby`
5515
+ * directly on `<kj-spinner>`? If so the accessible name is the referenced
5516
+ * element and we must not project a hidden duplicate. Read in the
5517
+ * constructor — by the time the template renders the directive may have
5518
+ * stamped its own attributes on the host.
5519
+ */
5520
+ hasAuthoredLabelledBy;
5521
+ /**
5522
+ * `true` when the consumer did **not** author `aria-labelledby` on the
5523
+ * wrapper — i.e. the spinner's accessible name is its `aria-label`. The
5524
+ * wrapper renders a `kjVisuallyHidden` copy of the label as inner text so
5525
+ * AT that prefers content over `aria-label` (or that announces a
5526
+ * `role="status"` region's body on insertion) still has a name to read.
5527
+ * A consumer-authored `aria-labelledby` opts out of that hidden copy to
5528
+ * avoid double-naming the host.
5529
+ */
5530
+ shouldRenderHiddenLabel = computed(() => !this.hasAuthoredLabelledBy, /* @ts-ignore */
5531
+ ...(ngDevMode ? [{ debugName: "shouldRenderHiddenLabel" }] : /* istanbul ignore next */ []));
5532
+ constructor() {
5533
+ this.hasAuthoredLabelledBy =
5534
+ this.el.nativeElement.hasAttribute('aria-labelledby');
5535
+ }
5536
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5537
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjSpinnerComponent, isStandalone: true, selector: "kj-spinner", inputs: { kjVariant: { classPropertyName: "kjVariant", publicName: "kjVariant", isSignal: true, isRequired: false, transformFunction: null }, kjSize: { classPropertyName: "kjSize", publicName: "kjSize", isSignal: true, isRequired: false, transformFunction: null }, kjAnimation: { classPropertyName: "kjAnimation", publicName: "kjAnimation", isSignal: true, isRequired: false, transformFunction: null }, kjAriaLabel: { classPropertyName: "kjAriaLabel", publicName: "kjAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variant": "kjVariant()", "attr.data-size": "kjSize()" }, classAttribute: "kj-spinner" }, hostDirectives: [{ directive: i1.KjSpinner, inputs: ["kjAnimation", "kjAnimation", "kjAriaLabel", "kjAriaLabel"] }], ngImport: i0, template: `
5538
+ <span class="kj-spinner__glyph" aria-hidden="true"></span>
5539
+ @if (shouldRenderHiddenLabel()) {
5540
+ <span kjVisuallyHidden>{{ kjAriaLabel() }}</span>
5541
+ }
5542
+ `, isInline: true, styles: ["@layer kj.component{.kj-spinner{--kj-spinner-size: 1.25rem;--kj-spinner-color: currentColor;--kj-spinner-track: color-mix(in srgb, currentColor 20%, transparent);--kj-spinner-duration: .7s;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--kj-spinner-size);block-size:var(--kj-spinner-size);color:var(--kj-spinner-color);pointer-events:none}.kj-spinner[data-size=xs]{--kj-spinner-size: .75rem}.kj-spinner[data-size=sm]{--kj-spinner-size: 1rem}.kj-spinner[data-size=md]{--kj-spinner-size: 1.25rem}.kj-spinner[data-size=lg]{--kj-spinner-size: 1.75rem}.kj-spinner[data-variant=neutral]{--kj-spinner-color: currentColor}.kj-spinner[data-variant=primary]{--kj-spinner-color: var(--kj-fg-primary)}.kj-spinner[data-variant=secondary]{--kj-spinner-color: var(--kj-fg-default)}.kj-spinner[data-variant=success]{--kj-spinner-color: var(--kj-fg-success, #16a34a)}.kj-spinner[data-variant=warning]{--kj-spinner-color: var(--kj-fg-warning, #d97706)}.kj-spinner[data-variant=error]{--kj-spinner-color: var(--kj-fg-danger, #dc2626)}.kj-spinner[data-variant=info]{--kj-spinner-color: var(--kj-fg-info, #2563eb)}.kj-spinner__glyph{display:inline-block;inline-size:100%;block-size:100%}.kj-spinner[data-animation=spin] .kj-spinner__glyph{border:2px solid var(--kj-spinner-track);border-block-start-color:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-spin var(--kj-spinner-duration) linear infinite}.kj-spinner[data-animation=pulse] .kj-spinner__glyph{background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-pulse calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots]{inline-size:auto}.kj-spinner[data-animation=dots] .kj-spinner__glyph{display:inline-flex;gap:calc(var(--kj-spinner-size) * .25);inline-size:auto;block-size:100%}.kj-spinner[data-animation=dots] .kj-spinner__glyph:before,.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .3);block-size:calc(var(--kj-spinner-size) * .3);background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-dots calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots] .kj-spinner__glyph{background:transparent}.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-animation=bars]{inline-size:auto}.kj-spinner[data-animation=bars] .kj-spinner__glyph{display:inline-flex;align-items:stretch;gap:calc(var(--kj-spinner-size) * .15);inline-size:auto;block-size:100%}.kj-spinner[data-animation=bars] .kj-spinner__glyph:before,.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .2);background:var(--kj-spinner-color);border-radius:calc(var(--kj-spinner-size) * .05);animation:kj-spinner-bars calc(var(--kj-spinner-duration) * 1.6) ease-in-out infinite;transform-origin:center}.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:before,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:after{animation:kj-spinner-reduced-motion 1.6s ease-in-out infinite!important}}@keyframes kj-spinner-spin{to{transform:rotate(360deg)}}@keyframes kj-spinner-pulse{0%,to{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}@keyframes kj-spinner-dots{0%,80%,to{transform:scale(.4);opacity:.4}40%{transform:scale(1);opacity:1}}@keyframes kj-spinner-bars{0%,40%,to{transform:scaleY(.4)}20%{transform:scaleY(1)}}@keyframes kj-spinner-reduced-motion{0%,to{opacity:.45}50%{opacity:1}}\n"], dependencies: [{ kind: "directive", type: KjVisuallyHidden, selector: "[kjVisuallyHidden]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5543
+ }
5544
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSpinnerComponent, decorators: [{
5545
+ type: Component,
5546
+ args: [{ selector: 'kj-spinner', standalone: true, imports: [KjVisuallyHidden], hostDirectives: [
5547
+ {
5548
+ directive: KjSpinner,
5549
+ // KjSpinner's own surface — kjVariant + kjSize live on its nested
5550
+ // KjVariant / KjSize and are not surfaced through this outer
5551
+ // composition; they are re-exposed as wrapper inputs below and wired
5552
+ // straight to the host's data-variant / data-size attributes.
5553
+ inputs: ['kjAnimation', 'kjAriaLabel'],
5554
+ },
5555
+ ], template: `
5556
+ <span class="kj-spinner__glyph" aria-hidden="true"></span>
5557
+ @if (shouldRenderHiddenLabel()) {
5558
+ <span kjVisuallyHidden>{{ kjAriaLabel() }}</span>
5559
+ }
5560
+ `, encapsulation: ViewEncapsulation.None, host: {
5561
+ 'class': 'kj-spinner',
5562
+ '[attr.data-variant]': 'kjVariant()',
5563
+ '[attr.data-size]': 'kjSize()',
5564
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-spinner{--kj-spinner-size: 1.25rem;--kj-spinner-color: currentColor;--kj-spinner-track: color-mix(in srgb, currentColor 20%, transparent);--kj-spinner-duration: .7s;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--kj-spinner-size);block-size:var(--kj-spinner-size);color:var(--kj-spinner-color);pointer-events:none}.kj-spinner[data-size=xs]{--kj-spinner-size: .75rem}.kj-spinner[data-size=sm]{--kj-spinner-size: 1rem}.kj-spinner[data-size=md]{--kj-spinner-size: 1.25rem}.kj-spinner[data-size=lg]{--kj-spinner-size: 1.75rem}.kj-spinner[data-variant=neutral]{--kj-spinner-color: currentColor}.kj-spinner[data-variant=primary]{--kj-spinner-color: var(--kj-fg-primary)}.kj-spinner[data-variant=secondary]{--kj-spinner-color: var(--kj-fg-default)}.kj-spinner[data-variant=success]{--kj-spinner-color: var(--kj-fg-success, #16a34a)}.kj-spinner[data-variant=warning]{--kj-spinner-color: var(--kj-fg-warning, #d97706)}.kj-spinner[data-variant=error]{--kj-spinner-color: var(--kj-fg-danger, #dc2626)}.kj-spinner[data-variant=info]{--kj-spinner-color: var(--kj-fg-info, #2563eb)}.kj-spinner__glyph{display:inline-block;inline-size:100%;block-size:100%}.kj-spinner[data-animation=spin] .kj-spinner__glyph{border:2px solid var(--kj-spinner-track);border-block-start-color:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-spin var(--kj-spinner-duration) linear infinite}.kj-spinner[data-animation=pulse] .kj-spinner__glyph{background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-pulse calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots]{inline-size:auto}.kj-spinner[data-animation=dots] .kj-spinner__glyph{display:inline-flex;gap:calc(var(--kj-spinner-size) * .25);inline-size:auto;block-size:100%}.kj-spinner[data-animation=dots] .kj-spinner__glyph:before,.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .3);block-size:calc(var(--kj-spinner-size) * .3);background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-dots calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots] .kj-spinner__glyph{background:transparent}.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-animation=bars]{inline-size:auto}.kj-spinner[data-animation=bars] .kj-spinner__glyph{display:inline-flex;align-items:stretch;gap:calc(var(--kj-spinner-size) * .15);inline-size:auto;block-size:100%}.kj-spinner[data-animation=bars] .kj-spinner__glyph:before,.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .2);background:var(--kj-spinner-color);border-radius:calc(var(--kj-spinner-size) * .05);animation:kj-spinner-bars calc(var(--kj-spinner-duration) * 1.6) ease-in-out infinite;transform-origin:center}.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:before,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:after{animation:kj-spinner-reduced-motion 1.6s ease-in-out infinite!important}}@keyframes kj-spinner-spin{to{transform:rotate(360deg)}}@keyframes kj-spinner-pulse{0%,to{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}@keyframes kj-spinner-dots{0%,80%,to{transform:scale(.4);opacity:.4}40%{transform:scale(1);opacity:1}}@keyframes kj-spinner-bars{0%,40%,to{transform:scaleY(.4)}20%{transform:scaleY(1)}}@keyframes kj-spinner-reduced-motion{0%,to{opacity:.45}50%{opacity:1}}\n"] }]
5565
+ }], ctorParameters: () => [], propDecorators: { kjVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjVariant", required: false }] }], kjSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSize", required: false }] }], kjAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAnimation", required: false }] }], kjAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaLabel", required: false }] }] } });
5566
+
5567
+ /**
5568
+ * Styled code editor — a themed `<kj-editor>` wrapping the headless `KjEditor`
5569
+ * directive (which wraps Monaco). Adds a kj-token-synced Monaco theme that
5570
+ * re-applies on theme switch, an optional toolbar (language badge + copy) and
5571
+ * status bar (cursor position + a keyboard-escape hint), reduced-motion, and a
5572
+ * loading region.
5573
+ *
5574
+ * Monaco is browser-only and heavy; it loads lazily after first render via
5575
+ * `KjEditorLoader`. Configure the source app-wide with `provideMonaco()`
5576
+ * (defaults to a CDN loader so the base bundle stays lean).
5577
+ *
5578
+ * @example
5579
+ * ```html
5580
+ * <kj-editor [(kjValue)]="code" kjLanguage="typescript" style="height:340px" />
5581
+ * ```
5582
+ * @doc-category Components/Data
5583
+ * @doc
5584
+ * @doc-name editor
5585
+ * @doc-is-main
5586
+ * @doc-description Themed Monaco code editor — syntax highlighting, two-way value, kj-theme sync, and AAA keyboard access.
5587
+ * @doc-example Default [full]
5588
+ * A TypeScript editor with the toolbar and status bar, two-way bound to a signal.
5589
+ * @doc-file editor.example.ts
5590
+ * @doc-example Languages [full]
5591
+ * Switch the `kjLanguage` to re-tokenise the same buffer across TS / HTML / CSS / JSON.
5592
+ * @doc-file editor.languages.example.ts
5593
+ * @doc-example Read-only [full]
5594
+ * A read-only viewer with the minimap enabled and line numbers on.
5595
+ * @doc-file editor.readonly.example.ts
5596
+ * @doc-example Options [full]
5597
+ * Toggle readonly, minimap, word wrap, line numbers and font size live.
5598
+ * @doc-file editor.options.example.ts
5599
+ *
5600
+ * @doc-keyboard
5601
+ * Tab Inserts a tab / indents (Monaco default)
5602
+ * Ctrl+M Toggles Tab-trapping — flips Tab to move focus in/out (no keyboard trap)
5603
+ * Alt+F1 Opens Monaco's accessibility help
5604
+ * Standard editing keys Arrow / Home / End / PageUp-Down / selection / undo-redo
5605
+ *
5606
+ * @doc-aria
5607
+ * aria-label Monaco's textarea is labelled from kjAriaLabel (defaults to "Code editor")
5608
+ * role=status The loading region announces the editor is loading
4052
5609
  */
4053
- class KjDropdownMenuComponent {
4054
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDropdownMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4055
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjDropdownMenuComponent, isStandalone: true, selector: "kj-dropdown-menu", host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-dropdown-menu{--kj-dropdown-menu-bg: var(--kj-bg-elevated);--kj-dropdown-menu-fg: var(--kj-fg-default);--kj-dropdown-menu-border-color: var(--kj-border-default);--kj-dropdown-menu-radius: var(--kj-radius-box);--kj-dropdown-menu-padding: var(--kj-space-xs);--kj-dropdown-menu-shadow: var(--kj-shadow-md);display:flex;flex-direction:column;box-sizing:border-box;min-width:12rem;max-width:min(20rem,calc(100vw - 2rem));background:var(--kj-dropdown-menu-bg);color:var(--kj-dropdown-menu-fg);border:var(--kj-border) solid var(--kj-dropdown-menu-border-color);border-radius:var(--kj-dropdown-menu-radius);padding:var(--kj-dropdown-menu-padding);font:.875rem / 1.5 var(--kj-font-sans);box-shadow:var(--kj-dropdown-menu-shadow);pointer-events:auto;z-index:1000}.kj-dropdown-menu[hidden]{display:none}.kj-dropdown-menu-item{--kj-dropdown-menu-item-padding-x: var(--kj-space-md);--kj-dropdown-menu-item-padding-y: var(--kj-space-sm);--kj-dropdown-menu-item-min-height: 2.75rem;--kj-dropdown-menu-item-radius: var(--kj-radius-field);--kj-dropdown-menu-item-hover-bg: var(--kj-bg-surface);--kj-dropdown-menu-item-active-bg: var(--kj-bg-field);display:flex;align-items:center;justify-content:flex-start;gap:var(--kj-space-sm);width:100%;min-height:var(--kj-dropdown-menu-item-min-height);box-sizing:border-box;padding:var(--kj-dropdown-menu-item-padding-y) var(--kj-dropdown-menu-item-padding-x);margin:0;background:transparent;color:inherit;border:none;border-radius:var(--kj-dropdown-menu-item-radius);font:inherit;text-align:start;cursor:pointer;-webkit-user-select:none;user-select:none}.kj-dropdown-menu-item:hover:not([data-disabled]){background:var(--kj-dropdown-menu-item-hover-bg)}.kj-dropdown-menu-item:focus-visible{outline:2px solid var(--kj-bg-primary);outline-offset:-2px}.kj-dropdown-menu-item[aria-current=true]{background:var(--kj-dropdown-menu-item-current-bg, var(--kj-bg-field));color:var(--kj-dropdown-menu-item-current-fg, var(--kj-fg-primary));font-weight:500}.kj-dropdown-menu-item[data-disabled]{cursor:not-allowed;opacity:.5}.kj-dropdown-menu-separator{display:block;height:1px;margin:var(--kj-space-xs) calc(var(--kj-space-xs) * -1);background:color-mix(in oklab,var(--kj-fg-default) 12%,transparent);border:0}.kj-dropdown-menu-label{display:block;padding:var(--kj-space-xs) var(--kj-space-md);font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--kj-fg-default);opacity:.65}.kj-dropdown-menu-group{display:flex;flex-direction:column}@media(prefers-reduced-motion:no-preference){.kj-dropdown-menu{transition:opacity .12s ease-out,transform .12s ease-out}.kj-dropdown-menu[data-state=closed]{opacity:0;transform:scale(.98)}.kj-dropdown-menu[data-state=open]{opacity:1;transform:scale(1)}}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5610
+ class KjEditorComponent {
5611
+ hostRef = inject(ElementRef);
5612
+ destroyRef = inject(DestroyRef);
5613
+ loader = inject(KjEditorLoader);
5614
+ editorHost = viewChild.required('editorHost');
5615
+ /** Two-way editor text. */
5616
+ kjValue = model('', /* @ts-ignore */
5617
+ ...(ngDevMode ? [{ debugName: "kjValue" }] : /* istanbul ignore next */ []));
5618
+ /** Code language — friendly name or Monaco id; short aliases (`ts`, `md`) normalised. */
5619
+ kjLanguage = input('plaintext', /* @ts-ignore */
5620
+ ...(ngDevMode ? [{ debugName: "kjLanguage" }] : /* istanbul ignore next */ []));
5621
+ /** Read-only mode. */
5622
+ kjReadonly = input(false, /* @ts-ignore */
5623
+ ...(ngDevMode ? [{ debugName: "kjReadonly" }] : /* istanbul ignore next */ []));
5624
+ /** Show the minimap. */
5625
+ kjMinimap = input(false, /* @ts-ignore */
5626
+ ...(ngDevMode ? [{ debugName: "kjMinimap" }] : /* istanbul ignore next */ []));
5627
+ /** Gutter line-number mode. */
5628
+ kjLineNumbers = input('on', /* @ts-ignore */
5629
+ ...(ngDevMode ? [{ debugName: "kjLineNumbers" }] : /* istanbul ignore next */ []));
5630
+ /** Soft wrap. */
5631
+ kjWordWrap = input('off', /* @ts-ignore */
5632
+ ...(ngDevMode ? [{ debugName: "kjWordWrap" }] : /* istanbul ignore next */ []));
5633
+ /** Font size in px. */
5634
+ kjFontSize = input(13, /* @ts-ignore */
5635
+ ...(ngDevMode ? [{ debugName: "kjFontSize" }] : /* istanbul ignore next */ []));
5636
+ /** Grow to fit content instead of filling the container (great for code snippets). */
5637
+ kjAutoHeight = input(false, /* @ts-ignore */
5638
+ ...(ngDevMode ? [{ debugName: "kjAutoHeight" }] : /* istanbul ignore next */ []));
5639
+ /** Cap for `kjAutoHeight` in px (content scrolls past it). Uncapped when unset. */
5640
+ kjMaxHeight = input(undefined, /* @ts-ignore */
5641
+ ...(ngDevMode ? [{ debugName: "kjMaxHeight" }] : /* istanbul ignore next */ []));
5642
+ /** Accessible name for the editor. */
5643
+ kjAriaLabel = input('Code editor', /* @ts-ignore */
5644
+ ...(ngDevMode ? [{ debugName: "kjAriaLabel" }] : /* istanbul ignore next */ []));
5645
+ /** Start with Tab moving focus out instead of indenting. */
5646
+ kjTabFocusMode = input(false, /* @ts-ignore */
5647
+ ...(ngDevMode ? [{ debugName: "kjTabFocusMode" }] : /* istanbul ignore next */ []));
5648
+ /** Escape hatch — merged last into Monaco's construction options. */
5649
+ kjOptions = input({}, /* @ts-ignore */
5650
+ ...(ngDevMode ? [{ debugName: "kjOptions" }] : /* istanbul ignore next */ []));
5651
+ /** Show the toolbar (language badge + copy button). */
5652
+ kjShowToolbar = input(true, /* @ts-ignore */
5653
+ ...(ngDevMode ? [{ debugName: "kjShowToolbar" }] : /* istanbul ignore next */ []));
5654
+ /** Show the status bar (cursor position + keyboard hint). */
5655
+ kjShowStatusBar = input(true, /* @ts-ignore */
5656
+ ...(ngDevMode ? [{ debugName: "kjShowStatusBar" }] : /* istanbul ignore next */ []));
5657
+ /** True until Monaco has mounted. */
5658
+ loading = signal(true, /* @ts-ignore */
5659
+ ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
5660
+ /** Cursor position for the status bar. */
5661
+ line = signal(1, /* @ts-ignore */
5662
+ ...(ngDevMode ? [{ debugName: "line" }] : /* istanbul ignore next */ []));
5663
+ column = signal(1, /* @ts-ignore */
5664
+ ...(ngDevMode ? [{ debugName: "column" }] : /* istanbul ignore next */ []));
5665
+ copied = signal(false, /* @ts-ignore */
5666
+ ...(ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []));
5667
+ /** Current kj-derived Monaco theme id, bound onto the directive. */
5668
+ themeId = signal('vs', /* @ts-ignore */
5669
+ ...(ngDevMode ? [{ debugName: "themeId" }] : /* istanbul ignore next */ []));
5670
+ /** Human label for the platform-appropriate tab-escape shortcut. */
5671
+ escapeHint = computed(() => 'Press Ctrl+M to toggle Tab trapping', /* @ts-ignore */
5672
+ ...(ngDevMode ? [{ debugName: "escapeHint" }] : /* istanbul ignore next */ []));
5673
+ monaco = null;
5674
+ constructor() {
5675
+ afterNextRender(() => {
5676
+ void this.syncTheme();
5677
+ // Re-apply the kj Monaco theme when the app theme switches.
5678
+ if (typeof MutationObserver !== 'undefined') {
5679
+ const obs = new MutationObserver(() => void this.syncTheme());
5680
+ obs.observe(document.documentElement, {
5681
+ attributes: true,
5682
+ attributeFilter: ['data-theme', 'class'],
5683
+ });
5684
+ this.destroyRef.onDestroy(() => obs.disconnect());
5685
+ }
5686
+ });
5687
+ }
5688
+ /** Wired from the directive's `kjReady` output. */
5689
+ onReady(editor) {
5690
+ this.loading.set(false);
5691
+ editor.onDidChangeCursorPosition((e) => {
5692
+ this.line.set(e.position.lineNumber);
5693
+ this.column.set(e.position.column);
5694
+ });
5695
+ void this.syncTheme();
5696
+ }
5697
+ async copy() {
5698
+ try {
5699
+ await navigator.clipboard.writeText(this.kjValue());
5700
+ this.copied.set(true);
5701
+ setTimeout(() => this.copied.set(false), 1500);
5702
+ }
5703
+ catch {
5704
+ // Clipboard unavailable (insecure context / denied) — no-op.
5705
+ }
5706
+ }
5707
+ /**
5708
+ * Read the resolved `--kj-*` surface tokens off the host, derive the scheme
5709
+ * from background luminance (theme-agnostic — works for any kj theme), define
5710
+ * a Monaco theme tinted with those tokens, and apply it globally.
5711
+ */
5712
+ async syncTheme() {
5713
+ if (!this.monaco) {
5714
+ try {
5715
+ this.monaco = await this.loader.load();
5716
+ }
5717
+ catch {
5718
+ return;
5719
+ }
5720
+ }
5721
+ const monaco = this.monaco;
5722
+ if (!monaco || typeof getComputedStyle === 'undefined')
5723
+ return;
5724
+ const bg = this.resolveColor('--kj-bg-surface') ?? [255, 255, 255];
5725
+ const fg = this.resolveColor('--kj-fg-default') ?? [30, 30, 30];
5726
+ const muted = this.resolveColor('--kj-fg-muted') ?? [130, 130, 130];
5727
+ const accent = this.resolveColor('--kj-bg-primary') ?? [90, 120, 255];
5728
+ const dark = luminance(bg) < 0.5;
5729
+ const id = dark ? 'kj-editor-dark' : 'kj-editor-light';
5730
+ monaco.editor.defineTheme(id, {
5731
+ base: dark ? 'vs-dark' : 'vs',
5732
+ inherit: true,
5733
+ rules: [],
5734
+ colors: {
5735
+ 'editor.background': hex(bg),
5736
+ 'editor.foreground': hex(fg),
5737
+ 'editorLineNumber.foreground': hex(muted),
5738
+ 'editorLineNumber.activeForeground': hex(fg),
5739
+ 'editorCursor.foreground': hex(accent),
5740
+ 'editor.selectionBackground': hex(accent) + '55',
5741
+ 'editorGutter.background': hex(bg),
5742
+ },
5743
+ });
5744
+ monaco.editor.setTheme(id);
5745
+ this.themeId.set(id);
5746
+ }
5747
+ /** Resolve a CSS custom property to [r,g,b] via a probe element. */
5748
+ resolveColor(varName) {
5749
+ const host = this.hostRef.nativeElement;
5750
+ const probe = document.createElement('span');
5751
+ probe.style.color = `var(${varName})`;
5752
+ probe.style.display = 'none';
5753
+ host.appendChild(probe);
5754
+ const rgb = getComputedStyle(probe).color;
5755
+ host.removeChild(probe);
5756
+ const m = rgb.match(/rgba?\(([^)]+)\)/);
5757
+ if (!m)
5758
+ return null;
5759
+ const parts = m[1].split(',').map((p) => parseFloat(p.trim()));
5760
+ if (parts.length < 3 || parts.some(Number.isNaN))
5761
+ return null;
5762
+ return [parts[0], parts[1], parts[2]];
5763
+ }
5764
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5765
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjEditorComponent, isStandalone: true, selector: "kj-editor", inputs: { kjValue: { classPropertyName: "kjValue", publicName: "kjValue", isSignal: true, isRequired: false, transformFunction: null }, kjLanguage: { classPropertyName: "kjLanguage", publicName: "kjLanguage", isSignal: true, isRequired: false, transformFunction: null }, kjReadonly: { classPropertyName: "kjReadonly", publicName: "kjReadonly", isSignal: true, isRequired: false, transformFunction: null }, kjMinimap: { classPropertyName: "kjMinimap", publicName: "kjMinimap", isSignal: true, isRequired: false, transformFunction: null }, kjLineNumbers: { classPropertyName: "kjLineNumbers", publicName: "kjLineNumbers", isSignal: true, isRequired: false, transformFunction: null }, kjWordWrap: { classPropertyName: "kjWordWrap", publicName: "kjWordWrap", isSignal: true, isRequired: false, transformFunction: null }, kjFontSize: { classPropertyName: "kjFontSize", publicName: "kjFontSize", isSignal: true, isRequired: false, transformFunction: null }, kjAutoHeight: { classPropertyName: "kjAutoHeight", publicName: "kjAutoHeight", isSignal: true, isRequired: false, transformFunction: null }, kjMaxHeight: { classPropertyName: "kjMaxHeight", publicName: "kjMaxHeight", isSignal: true, isRequired: false, transformFunction: null }, kjAriaLabel: { classPropertyName: "kjAriaLabel", publicName: "kjAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, kjTabFocusMode: { classPropertyName: "kjTabFocusMode", publicName: "kjTabFocusMode", isSignal: true, isRequired: false, transformFunction: null }, kjOptions: { classPropertyName: "kjOptions", publicName: "kjOptions", isSignal: true, isRequired: false, transformFunction: null }, kjShowToolbar: { classPropertyName: "kjShowToolbar", publicName: "kjShowToolbar", isSignal: true, isRequired: false, transformFunction: null }, kjShowStatusBar: { classPropertyName: "kjShowStatusBar", publicName: "kjShowStatusBar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { kjValue: "kjValueChange" }, host: { properties: { "attr.data-auto-height": "kjAutoHeight() ? '' : null" } }, viewQueries: [{ propertyName: "editorHost", first: true, predicate: ["editorHost"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"kj-editor-wrap\">\n @if (kjShowToolbar()) {\n <div class=\"kj-editor-toolbar\">\n <span class=\"kj-editor-lang\">{{ kjLanguage() }}</span>\n <span class=\"kj-editor-spacer\"></span>\n <button\n type=\"button\"\n class=\"kj-editor-copy\"\n (click)=\"copy()\"\n [attr.aria-label]=\"copied() ? 'Copied' : 'Copy code'\"\n >\n {{ copied() ? 'Copied' : 'Copy' }}\n </button>\n </div>\n }\n\n <div class=\"kj-editor-body\">\n <div\n #editorHost\n class=\"kj-editor-host\"\n kjEditor\n [(kjValue)]=\"kjValue\"\n [kjLanguage]=\"kjLanguage()\"\n [kjReadonly]=\"kjReadonly()\"\n [kjMinimap]=\"kjMinimap()\"\n [kjLineNumbers]=\"kjLineNumbers()\"\n [kjWordWrap]=\"kjWordWrap()\"\n [kjFontSize]=\"kjFontSize()\"\n [kjAutoHeight]=\"kjAutoHeight()\"\n [kjMaxHeight]=\"kjMaxHeight()\"\n [kjAriaLabel]=\"kjAriaLabel()\"\n [kjTabFocusMode]=\"kjTabFocusMode()\"\n [kjTheme]=\"themeId()\"\n [kjOptions]=\"kjOptions()\"\n (kjReady)=\"onReady($event)\"\n ></div>\n\n @if (loading()) {\n <div class=\"kj-editor-loading\" role=\"status\" aria-live=\"polite\">\n <kj-spinner kjAriaLabel=\"Loading editor\" />\n </div>\n }\n </div>\n\n @if (kjShowStatusBar()) {\n <div class=\"kj-editor-status\">\n <span class=\"kj-editor-pos\">Ln {{ line() }}, Col {{ column() }}</span>\n <span class=\"kj-editor-spacer\"></span>\n <span class=\"kj-editor-hint\">{{ escapeHint() }}</span>\n </div>\n }\n</div>\n", styles: [":host{display:block;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-md, 0);overflow:hidden;background:var(--kj-bg-surface)}.kj-editor-wrap{display:flex;flex-direction:column;height:100%;min-height:12rem}:host([data-auto-height]){height:auto}:host([data-auto-height]) .kj-editor-wrap{height:auto;min-height:0}:host([data-auto-height]) .kj-editor-body{position:static;flex:none;min-height:3rem}:host([data-auto-height]) .kj-editor-host{position:relative;inset:auto}.kj-editor-toolbar,.kj-editor-status{display:flex;align-items:center;gap:var(--kj-space-sm);padding:var(--kj-space-sm) var(--kj-space-lg);background:var(--kj-bg-body);flex-shrink:0}.kj-editor-toolbar{border-bottom:1px solid var(--kj-border-default)}.kj-editor-status{border-top:1px solid var(--kj-border-default)}.kj-editor-spacer{flex:1}.kj-editor-lang{font-family:var(--kj-font-mono);font-size:.65rem;letter-spacing:.12em;text-transform:uppercase;color:var(--kj-fg-primary);background:color-mix(in oklab,var(--kj-bg-primary) 8%,transparent);padding:.15rem var(--kj-space-sm);border:1px solid color-mix(in oklab,var(--kj-bg-primary) 22%,transparent)}.kj-editor-copy{background:none;border:none;color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.7rem;letter-spacing:.06em;cursor:pointer;min-height:44px;min-width:44px;padding:0 var(--kj-space-sm);transition:color .15s}.kj-editor-copy:hover{color:var(--kj-fg-default)}.kj-editor-copy:focus-visible{outline:2px solid var(--kj-border-focus, var(--kj-bg-primary));outline-offset:2px}.kj-editor-pos{font-family:var(--kj-font-mono);font-size:.7rem;color:var(--kj-fg-muted)}.kj-editor-hint{font-size:.7rem;color:var(--kj-fg-muted)}.kj-editor-body{position:relative;flex:1;min-height:8rem}.kj-editor-host{position:absolute;inset:0;overflow:hidden}.kj-editor-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:var(--kj-bg-surface);z-index:1}.kj-editor-host ::ng-deep .monaco-editor,.kj-editor-host ::ng-deep .monaco-editor-background,.kj-editor-host ::ng-deep .monaco-editor .margin{background-color:var(--kj-bg-surface)!important}.kj-editor-host ::ng-deep .monaco-editor .scrollbar .slider{background:var(--kj-bg-field, var(--kj-bg-elevated))!important}@media(prefers-reduced-motion:reduce){.kj-editor-copy{transition:none}}\n"], dependencies: [{ kind: "directive", type: KjEditor, selector: "[kjEditor]", inputs: ["kjValue", "kjLanguage", "kjReadonly", "kjMinimap", "kjLineNumbers", "kjWordWrap", "kjFontSize", "kjAutoHeight", "kjMaxHeight", "kjTheme", "kjAriaLabel", "kjTabFocusMode", "kjOptions"], outputs: ["kjValueChange", "kjReady"], exportAs: ["kjEditor"] }, { kind: "component", type: KjSpinnerComponent, selector: "kj-spinner", inputs: ["kjVariant", "kjSize", "kjAnimation", "kjAriaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4056
5766
  }
4057
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjDropdownMenuComponent, decorators: [{
5767
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjEditorComponent, decorators: [{
4058
5768
  type: Component,
4059
- args: [{ selector: 'kj-dropdown-menu', standalone: true, imports: [
4060
- KjDropdownMenuTrigger,
4061
- KjDropdownMenuContent,
4062
- KjDropdownMenuItem,
4063
- KjDropdownMenuSeparator,
4064
- KjDropdownMenuLabel,
4065
- KjDropdownMenuGroup,
4066
- ], template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-dropdown-menu{--kj-dropdown-menu-bg: var(--kj-bg-elevated);--kj-dropdown-menu-fg: var(--kj-fg-default);--kj-dropdown-menu-border-color: var(--kj-border-default);--kj-dropdown-menu-radius: var(--kj-radius-box);--kj-dropdown-menu-padding: var(--kj-space-xs);--kj-dropdown-menu-shadow: var(--kj-shadow-md);display:flex;flex-direction:column;box-sizing:border-box;min-width:12rem;max-width:min(20rem,calc(100vw - 2rem));background:var(--kj-dropdown-menu-bg);color:var(--kj-dropdown-menu-fg);border:var(--kj-border) solid var(--kj-dropdown-menu-border-color);border-radius:var(--kj-dropdown-menu-radius);padding:var(--kj-dropdown-menu-padding);font:.875rem / 1.5 var(--kj-font-sans);box-shadow:var(--kj-dropdown-menu-shadow);pointer-events:auto;z-index:1000}.kj-dropdown-menu[hidden]{display:none}.kj-dropdown-menu-item{--kj-dropdown-menu-item-padding-x: var(--kj-space-md);--kj-dropdown-menu-item-padding-y: var(--kj-space-sm);--kj-dropdown-menu-item-min-height: 2.75rem;--kj-dropdown-menu-item-radius: var(--kj-radius-field);--kj-dropdown-menu-item-hover-bg: var(--kj-bg-surface);--kj-dropdown-menu-item-active-bg: var(--kj-bg-field);display:flex;align-items:center;justify-content:flex-start;gap:var(--kj-space-sm);width:100%;min-height:var(--kj-dropdown-menu-item-min-height);box-sizing:border-box;padding:var(--kj-dropdown-menu-item-padding-y) var(--kj-dropdown-menu-item-padding-x);margin:0;background:transparent;color:inherit;border:none;border-radius:var(--kj-dropdown-menu-item-radius);font:inherit;text-align:start;cursor:pointer;-webkit-user-select:none;user-select:none}.kj-dropdown-menu-item:hover:not([data-disabled]){background:var(--kj-dropdown-menu-item-hover-bg)}.kj-dropdown-menu-item:focus-visible{outline:2px solid var(--kj-bg-primary);outline-offset:-2px}.kj-dropdown-menu-item[aria-current=true]{background:var(--kj-dropdown-menu-item-current-bg, var(--kj-bg-field));color:var(--kj-dropdown-menu-item-current-fg, var(--kj-fg-primary));font-weight:500}.kj-dropdown-menu-item[data-disabled]{cursor:not-allowed;opacity:.5}.kj-dropdown-menu-separator{display:block;height:1px;margin:var(--kj-space-xs) calc(var(--kj-space-xs) * -1);background:color-mix(in oklab,var(--kj-fg-default) 12%,transparent);border:0}.kj-dropdown-menu-label{display:block;padding:var(--kj-space-xs) var(--kj-space-md);font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--kj-fg-default);opacity:.65}.kj-dropdown-menu-group{display:flex;flex-direction:column}@media(prefers-reduced-motion:no-preference){.kj-dropdown-menu{transition:opacity .12s ease-out,transform .12s ease-out}.kj-dropdown-menu[data-state=closed]{opacity:0;transform:scale(.98)}.kj-dropdown-menu[data-state=open]{opacity:1;transform:scale(1)}}}\n"] }]
4067
- }] });
5769
+ args: [{ selector: 'kj-editor', standalone: true, imports: [KjEditor, KjSpinnerComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
5770
+ '[attr.data-auto-height]': "kjAutoHeight() ? '' : null",
5771
+ }, template: "<div class=\"kj-editor-wrap\">\n @if (kjShowToolbar()) {\n <div class=\"kj-editor-toolbar\">\n <span class=\"kj-editor-lang\">{{ kjLanguage() }}</span>\n <span class=\"kj-editor-spacer\"></span>\n <button\n type=\"button\"\n class=\"kj-editor-copy\"\n (click)=\"copy()\"\n [attr.aria-label]=\"copied() ? 'Copied' : 'Copy code'\"\n >\n {{ copied() ? 'Copied' : 'Copy' }}\n </button>\n </div>\n }\n\n <div class=\"kj-editor-body\">\n <div\n #editorHost\n class=\"kj-editor-host\"\n kjEditor\n [(kjValue)]=\"kjValue\"\n [kjLanguage]=\"kjLanguage()\"\n [kjReadonly]=\"kjReadonly()\"\n [kjMinimap]=\"kjMinimap()\"\n [kjLineNumbers]=\"kjLineNumbers()\"\n [kjWordWrap]=\"kjWordWrap()\"\n [kjFontSize]=\"kjFontSize()\"\n [kjAutoHeight]=\"kjAutoHeight()\"\n [kjMaxHeight]=\"kjMaxHeight()\"\n [kjAriaLabel]=\"kjAriaLabel()\"\n [kjTabFocusMode]=\"kjTabFocusMode()\"\n [kjTheme]=\"themeId()\"\n [kjOptions]=\"kjOptions()\"\n (kjReady)=\"onReady($event)\"\n ></div>\n\n @if (loading()) {\n <div class=\"kj-editor-loading\" role=\"status\" aria-live=\"polite\">\n <kj-spinner kjAriaLabel=\"Loading editor\" />\n </div>\n }\n </div>\n\n @if (kjShowStatusBar()) {\n <div class=\"kj-editor-status\">\n <span class=\"kj-editor-pos\">Ln {{ line() }}, Col {{ column() }}</span>\n <span class=\"kj-editor-spacer\"></span>\n <span class=\"kj-editor-hint\">{{ escapeHint() }}</span>\n </div>\n }\n</div>\n", styles: [":host{display:block;border:1px solid var(--kj-border-default);border-radius:var(--kj-radius-md, 0);overflow:hidden;background:var(--kj-bg-surface)}.kj-editor-wrap{display:flex;flex-direction:column;height:100%;min-height:12rem}:host([data-auto-height]){height:auto}:host([data-auto-height]) .kj-editor-wrap{height:auto;min-height:0}:host([data-auto-height]) .kj-editor-body{position:static;flex:none;min-height:3rem}:host([data-auto-height]) .kj-editor-host{position:relative;inset:auto}.kj-editor-toolbar,.kj-editor-status{display:flex;align-items:center;gap:var(--kj-space-sm);padding:var(--kj-space-sm) var(--kj-space-lg);background:var(--kj-bg-body);flex-shrink:0}.kj-editor-toolbar{border-bottom:1px solid var(--kj-border-default)}.kj-editor-status{border-top:1px solid var(--kj-border-default)}.kj-editor-spacer{flex:1}.kj-editor-lang{font-family:var(--kj-font-mono);font-size:.65rem;letter-spacing:.12em;text-transform:uppercase;color:var(--kj-fg-primary);background:color-mix(in oklab,var(--kj-bg-primary) 8%,transparent);padding:.15rem var(--kj-space-sm);border:1px solid color-mix(in oklab,var(--kj-bg-primary) 22%,transparent)}.kj-editor-copy{background:none;border:none;color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.7rem;letter-spacing:.06em;cursor:pointer;min-height:44px;min-width:44px;padding:0 var(--kj-space-sm);transition:color .15s}.kj-editor-copy:hover{color:var(--kj-fg-default)}.kj-editor-copy:focus-visible{outline:2px solid var(--kj-border-focus, var(--kj-bg-primary));outline-offset:2px}.kj-editor-pos{font-family:var(--kj-font-mono);font-size:.7rem;color:var(--kj-fg-muted)}.kj-editor-hint{font-size:.7rem;color:var(--kj-fg-muted)}.kj-editor-body{position:relative;flex:1;min-height:8rem}.kj-editor-host{position:absolute;inset:0;overflow:hidden}.kj-editor-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:var(--kj-bg-surface);z-index:1}.kj-editor-host ::ng-deep .monaco-editor,.kj-editor-host ::ng-deep .monaco-editor-background,.kj-editor-host ::ng-deep .monaco-editor .margin{background-color:var(--kj-bg-surface)!important}.kj-editor-host ::ng-deep .monaco-editor .scrollbar .slider{background:var(--kj-bg-field, var(--kj-bg-elevated))!important}@media(prefers-reduced-motion:reduce){.kj-editor-copy{transition:none}}\n"] }]
5772
+ }], ctorParameters: () => [], propDecorators: { editorHost: [{ type: i0.ViewChild, args: ['editorHost', { isSignal: true }] }], kjValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjValue", required: false }] }, { type: i0.Output, args: ["kjValueChange"] }], kjLanguage: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLanguage", required: false }] }], kjReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjReadonly", required: false }] }], kjMinimap: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjMinimap", required: false }] }], kjLineNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLineNumbers", required: false }] }], kjWordWrap: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjWordWrap", required: false }] }], kjFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjFontSize", required: false }] }], kjAutoHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAutoHeight", required: false }] }], kjMaxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjMaxHeight", required: false }] }], kjAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaLabel", required: false }] }], kjTabFocusMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjTabFocusMode", required: false }] }], kjOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjOptions", required: false }] }], kjShowToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjShowToolbar", required: false }] }], kjShowStatusBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjShowStatusBar", required: false }] }] } });
5773
+ /** Relative luminance (0 dark – 1 light) of an [r,g,b] triple. */
5774
+ function luminance([r, g, b]) {
5775
+ return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
5776
+ }
5777
+ /** [r,g,b] → `#rrggbb`. */
5778
+ function hex([r, g, b]) {
5779
+ const h = (n) => Math.max(0, Math.min(255, Math.round(n)))
5780
+ .toString(16)
5781
+ .padStart(2, '0');
5782
+ return `#${h(r)}${h(g)}${h(b)}`;
5783
+ }
4068
5784
 
4069
5785
  const KJ_EMPTY_STATE_SIZE_PRESET = {
4070
5786
  values: ['sm', 'md', 'lg'],
@@ -5163,11 +6879,20 @@ function encodeSvgDataUrl(svg) {
5163
6879
  .replace(/>/g, '%3E');
5164
6880
  return `url("data:image/svg+xml;utf8,${encoded}")`;
5165
6881
  }
5166
- /** Convert PascalCase ("AArrowDown") → kebab-case ("a-arrow-down"). */
6882
+ /**
6883
+ * Convert PascalCase ("AArrowDown") → kebab-case ("a-arrow-down").
6884
+ *
6885
+ * Lucide separates a trailing number from its word with a hyphen and keeps the
6886
+ * digits grouped ("Heading1" → "heading-1", "Clock10" → "clock-10"), so a
6887
+ * letter→digit boundary also gets a hyphen. Without this, digit-bearing icons
6888
+ * (headings, clock-1…12, columns-2, …) resolve to a key that never matches the
6889
+ * requested name and render blank.
6890
+ */
5167
6891
  function pascalToKebab(name) {
5168
6892
  return name
5169
6893
  .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
5170
6894
  .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
6895
+ .replace(/([a-zA-Z])([0-9])/g, '$1-$2')
5171
6896
  .toLowerCase();
5172
6897
  }
5173
6898
  /** Lazily build the kebab-name → encoded-data-url map once per app. */
@@ -5205,7 +6930,7 @@ function buildLucideRegistry() {
5205
6930
  * ```
5206
6931
  *
5207
6932
  * @doc-example Gallery
5208
- * @doc-file ../icon.gallery.example.ts
6933
+ * @doc-file ../_examples/icon.gallery.example.ts
5209
6934
  *
5210
6935
  * @doc-css-var
5211
6936
  * --kj-icon — Resolved icon value (url("...") or "glyph"). Set by the directive — read by the rendered .kj-icon.
@@ -10715,6 +12440,800 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
10715
12440
  }]
10716
12441
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dot: [{ type: i0.ViewChild, args: ['dot', { isSignal: true }] }] } });
10717
12442
 
12443
+ /**
12444
+ * Build an inline-format toggle feature. These need no package loading — inline
12445
+ * formatting uses the core `FORMAT_TEXT_COMMAND` — so the whole feature is a
12446
+ * toolbar toggle plus an optional keyboard shortcut.
12447
+ */
12448
+ function inlineFormat(format, icon, label, order, shortcut, ariaKeyshortcuts) {
12449
+ return {
12450
+ name: format,
12451
+ setup: shortcut
12452
+ ? (ctx) => ctx.registerShortcut(shortcut, () => ctx.toggleInlineFormat(format))
12453
+ : undefined,
12454
+ toolbar: [
12455
+ {
12456
+ id: format,
12457
+ group: 'format',
12458
+ order,
12459
+ icon,
12460
+ label,
12461
+ ariaKeyshortcuts,
12462
+ kind: 'toggle',
12463
+ isActive: (state) => state.activeFormats.has(format),
12464
+ run: (ctx) => ctx.toggleInlineFormat(format),
12465
+ },
12466
+ ],
12467
+ };
12468
+ }
12469
+ /** Bold (Ctrl/Cmd+B). */
12470
+ function bold() {
12471
+ return inlineFormat('bold', 'bold', 'Bold', 10, 'mod+b', 'Control+B');
12472
+ }
12473
+ /** Italic (Ctrl/Cmd+I). */
12474
+ function italic() {
12475
+ return inlineFormat('italic', 'italic', 'Italic', 20, 'mod+i', 'Control+I');
12476
+ }
12477
+ /** Underline (Ctrl/Cmd+U). */
12478
+ function underline() {
12479
+ return inlineFormat('underline', 'underline', 'Underline', 30, 'mod+u', 'Control+U');
12480
+ }
12481
+ /** Strikethrough. */
12482
+ function strike() {
12483
+ return inlineFormat('strikethrough', 'strikethrough', 'Strikethrough', 40);
12484
+ }
12485
+ /** Inline code. */
12486
+ function inlineCode() {
12487
+ return inlineFormat('code', 'code', 'Inline code', 50);
12488
+ }
12489
+
12490
+ /**
12491
+ * Heading feature. Lazily loads `@lexical/rich-text` for the heading node +
12492
+ * creator, and contributes one toolbar toggle per configured level.
12493
+ */
12494
+ function heading(options) {
12495
+ const levels = options?.levels ?? [1, 2, 3];
12496
+ let mod;
12497
+ return {
12498
+ name: 'heading',
12499
+ async load() {
12500
+ mod = await import('@lexical/rich-text');
12501
+ },
12502
+ nodes: () => [mod.HeadingNode],
12503
+ toolbar: levels.map((level, index) => {
12504
+ const tag = `h${level}`;
12505
+ return {
12506
+ id: `heading-${level}`,
12507
+ group: 'block',
12508
+ order: index,
12509
+ icon: `heading-${level}`,
12510
+ label: `Heading ${level}`,
12511
+ kind: 'toggle',
12512
+ isActive: (state) => state.blockType === tag,
12513
+ run: (ctx) => {
12514
+ if (ctx.state.blockType === tag)
12515
+ ctx.setParagraph();
12516
+ else
12517
+ ctx.setBlock(() => mod.$createHeadingNode(tag));
12518
+ },
12519
+ };
12520
+ }),
12521
+ };
12522
+ }
12523
+
12524
+ // `registerList` sets up transforms + commands editor-wide; run it once even if
12525
+ // both bullet and ordered list features are enabled.
12526
+ const listRegistered = new WeakSet();
12527
+ function ensureList(editor, mod) {
12528
+ if (listRegistered.has(editor))
12529
+ return () => { };
12530
+ listRegistered.add(editor);
12531
+ const unregister = mod.registerList(editor);
12532
+ return () => {
12533
+ listRegistered.delete(editor);
12534
+ unregister();
12535
+ };
12536
+ }
12537
+ /** Bullet (unordered) list. Lazily loads `@lexical/list`. */
12538
+ function bulletList() {
12539
+ let mod;
12540
+ return {
12541
+ name: 'bullet-list',
12542
+ async load() {
12543
+ mod = await import('@lexical/list');
12544
+ },
12545
+ nodes: () => [mod.ListNode, mod.ListItemNode],
12546
+ setup: (ctx) => ensureList(ctx.editor, mod),
12547
+ toolbar: [
12548
+ {
12549
+ id: 'bullet-list',
12550
+ group: 'list',
12551
+ order: 0,
12552
+ icon: 'list',
12553
+ label: 'Bullet list',
12554
+ kind: 'toggle',
12555
+ isActive: (state) => state.blockType === 'bullet',
12556
+ run: (ctx) => ctx.state.blockType === 'bullet'
12557
+ ? ctx.dispatch(mod.REMOVE_LIST_COMMAND, undefined)
12558
+ : ctx.dispatch(mod.INSERT_UNORDERED_LIST_COMMAND, undefined),
12559
+ },
12560
+ ],
12561
+ };
12562
+ }
12563
+ /** Ordered (numbered) list. Lazily loads `@lexical/list`. */
12564
+ function orderedList() {
12565
+ let mod;
12566
+ return {
12567
+ name: 'ordered-list',
12568
+ async load() {
12569
+ mod = await import('@lexical/list');
12570
+ },
12571
+ nodes: () => [mod.ListNode, mod.ListItemNode],
12572
+ setup: (ctx) => ensureList(ctx.editor, mod),
12573
+ toolbar: [
12574
+ {
12575
+ id: 'ordered-list',
12576
+ group: 'list',
12577
+ order: 1,
12578
+ icon: 'list-ordered',
12579
+ label: 'Numbered list',
12580
+ kind: 'toggle',
12581
+ isActive: (state) => state.blockType === 'number',
12582
+ run: (ctx) => ctx.state.blockType === 'number'
12583
+ ? ctx.dispatch(mod.REMOVE_LIST_COMMAND, undefined)
12584
+ : ctx.dispatch(mod.INSERT_ORDERED_LIST_COMMAND, undefined),
12585
+ },
12586
+ ],
12587
+ };
12588
+ }
12589
+
12590
+ /** Blockquote feature. Lazily loads `@lexical/rich-text` for the quote node. */
12591
+ function quote() {
12592
+ let mod;
12593
+ return {
12594
+ name: 'quote',
12595
+ async load() {
12596
+ mod = await import('@lexical/rich-text');
12597
+ },
12598
+ nodes: () => [mod.QuoteNode],
12599
+ toolbar: [
12600
+ {
12601
+ id: 'quote',
12602
+ group: 'block',
12603
+ order: 10,
12604
+ icon: 'quote',
12605
+ label: 'Quote',
12606
+ kind: 'toggle',
12607
+ isActive: (state) => state.blockType === 'quote',
12608
+ run: (ctx) => ctx.state.blockType === 'quote'
12609
+ ? ctx.setParagraph()
12610
+ : ctx.setBlock(() => mod.$createQuoteNode()),
12611
+ },
12612
+ ],
12613
+ };
12614
+ }
12615
+
12616
+ /** Code block feature. Lazily loads `@lexical/code` (and its Prism grammars). */
12617
+ function codeBlock() {
12618
+ let mod;
12619
+ return {
12620
+ name: 'code-block',
12621
+ async load() {
12622
+ mod = await import('@lexical/code');
12623
+ },
12624
+ nodes: () => [mod.CodeNode, mod.CodeHighlightNode],
12625
+ toolbar: [
12626
+ {
12627
+ id: 'code-block',
12628
+ group: 'block',
12629
+ order: 20,
12630
+ icon: 'square-code',
12631
+ label: 'Code block',
12632
+ kind: 'toggle',
12633
+ isActive: (state) => state.blockType === 'code',
12634
+ run: (ctx) => ctx.state.blockType === 'code'
12635
+ ? ctx.setParagraph()
12636
+ : ctx.setBlock(() => mod.$createCodeNode()),
12637
+ },
12638
+ ],
12639
+ };
12640
+ }
12641
+
12642
+ /**
12643
+ * Link editor overlay contributed by the `link` feature. Rendered by the RTE
12644
+ * component inside a `role="dialog"` popover; it edits/removes the link at the
12645
+ * caret. Not part of the public API — surfaced via the feature's `overlay`.
12646
+ */
12647
+ class LinkEditor {
12648
+ data = injectRteOverlayData();
12649
+ url = signal(this.data.url ?? '', /* @ts-ignore */
12650
+ ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
12651
+ input = viewChild('input', /* @ts-ignore */
12652
+ ...(ngDevMode ? [{ debugName: "input" }] : /* istanbul ignore next */ []));
12653
+ constructor() {
12654
+ afterNextRender(() => this.input()?.nativeElement.focus());
12655
+ }
12656
+ onApply(event) {
12657
+ event.preventDefault();
12658
+ this.data.apply(this.url().trim());
12659
+ }
12660
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: LinkEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
12661
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: LinkEditor, isStandalone: true, selector: "kj-rte-link-editor", viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: `
12662
+ <form class="kj-rte__overlay-form" (submit)="onApply($event)">
12663
+ <label class="kj-rte__overlay-label" for="kj-rte-link-url">URL</label>
12664
+ <input
12665
+ #input
12666
+ id="kj-rte-link-url"
12667
+ class="kj-rte__overlay-input"
12668
+ type="url"
12669
+ placeholder="https://example.com"
12670
+ [value]="url()"
12671
+ (input)="url.set($any($event.target).value)"
12672
+ (keydown.escape)="data.close()"
12673
+ />
12674
+ <div class="kj-rte__overlay-actions">
12675
+ <button type="submit" class="kj-rte__overlay-btn">Apply</button>
12676
+ @if (url()) {
12677
+ <button type="button" class="kj-rte__overlay-btn" (click)="data.remove()">Remove</button>
12678
+ }
12679
+ <button type="button" class="kj-rte__overlay-btn" (click)="data.close()">Cancel</button>
12680
+ </div>
12681
+ </form>
12682
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
12683
+ }
12684
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: LinkEditor, decorators: [{
12685
+ type: Component,
12686
+ args: [{
12687
+ selector: 'kj-rte-link-editor',
12688
+ standalone: true,
12689
+ template: `
12690
+ <form class="kj-rte__overlay-form" (submit)="onApply($event)">
12691
+ <label class="kj-rte__overlay-label" for="kj-rte-link-url">URL</label>
12692
+ <input
12693
+ #input
12694
+ id="kj-rte-link-url"
12695
+ class="kj-rte__overlay-input"
12696
+ type="url"
12697
+ placeholder="https://example.com"
12698
+ [value]="url()"
12699
+ (input)="url.set($any($event.target).value)"
12700
+ (keydown.escape)="data.close()"
12701
+ />
12702
+ <div class="kj-rte__overlay-actions">
12703
+ <button type="submit" class="kj-rte__overlay-btn">Apply</button>
12704
+ @if (url()) {
12705
+ <button type="button" class="kj-rte__overlay-btn" (click)="data.remove()">Remove</button>
12706
+ }
12707
+ <button type="button" class="kj-rte__overlay-btn" (click)="data.close()">Cancel</button>
12708
+ </div>
12709
+ </form>
12710
+ `,
12711
+ changeDetection: ChangeDetectionStrategy.OnPush,
12712
+ }]
12713
+ }], ctorParameters: () => [], propDecorators: { input: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }] } });
12714
+
12715
+ /**
12716
+ * Link feature. Lazily loads core `lexical` (for selection reads) and
12717
+ * `@lexical/link`. Contributes the link node, a Ctrl/Cmd+K shortcut, a toolbar
12718
+ * toggle, and the link-editor overlay.
12719
+ */
12720
+ function link() {
12721
+ let lex;
12722
+ let mod;
12723
+ function selectedUrl(ctx) {
12724
+ return ctx.read(() => {
12725
+ const selection = lex.$getSelection();
12726
+ if (!lex.$isRangeSelection(selection))
12727
+ return '';
12728
+ for (const node of selection.getNodes()) {
12729
+ const link = mod.$isLinkNode(node)
12730
+ ? node
12731
+ : mod.$isLinkNode(node.getParent())
12732
+ ? node.getParent()
12733
+ : null;
12734
+ if (link && mod.$isLinkNode(link))
12735
+ return link.getURL();
12736
+ }
12737
+ return '';
12738
+ });
12739
+ }
12740
+ function open(ctx) {
12741
+ ctx.openOverlay('link', {
12742
+ url: selectedUrl(ctx),
12743
+ apply: (url) => {
12744
+ ctx.update(() => mod.$toggleLink(url ? url : null));
12745
+ ctx.closeOverlay();
12746
+ ctx.focus();
12747
+ ctx.announce(url ? 'Link added' : 'Link removed');
12748
+ },
12749
+ remove: () => {
12750
+ ctx.update(() => mod.$toggleLink(null));
12751
+ ctx.closeOverlay();
12752
+ ctx.focus();
12753
+ ctx.announce('Link removed');
12754
+ },
12755
+ close: () => {
12756
+ ctx.closeOverlay();
12757
+ ctx.focus();
12758
+ },
12759
+ });
12760
+ }
12761
+ return {
12762
+ name: 'link',
12763
+ async load() {
12764
+ [lex, mod] = await Promise.all([import('lexical'), import('@lexical/link')]);
12765
+ },
12766
+ nodes: () => [mod.LinkNode],
12767
+ setup: (ctx) => ctx.registerShortcut('mod+k', () => open(ctx)),
12768
+ toolbar: [
12769
+ {
12770
+ id: 'link',
12771
+ group: 'insert',
12772
+ order: 0,
12773
+ icon: 'link',
12774
+ label: 'Link',
12775
+ ariaKeyshortcuts: 'Control+K',
12776
+ kind: 'toggle',
12777
+ isActive: (state) => state.isLink,
12778
+ run: (ctx) => open(ctx),
12779
+ },
12780
+ ],
12781
+ overlay: [{ id: 'link', label: 'Edit link', component: LinkEditor }],
12782
+ };
12783
+ }
12784
+
12785
+ /**
12786
+ * Image editor overlay contributed by the `image` feature. Collects a URL + alt
12787
+ * text (always require alt for WCAG 1.1.1) and inserts an image node.
12788
+ */
12789
+ class ImageEditor {
12790
+ data = injectRteOverlayData();
12791
+ src = signal('', /* @ts-ignore */
12792
+ ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
12793
+ alt = signal('', /* @ts-ignore */
12794
+ ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
12795
+ input = viewChild('input', /* @ts-ignore */
12796
+ ...(ngDevMode ? [{ debugName: "input" }] : /* istanbul ignore next */ []));
12797
+ constructor() {
12798
+ afterNextRender(() => this.input()?.nativeElement.focus());
12799
+ }
12800
+ onInsert(event) {
12801
+ event.preventDefault();
12802
+ const src = this.src().trim();
12803
+ if (src)
12804
+ this.data.insert(src, this.alt().trim());
12805
+ }
12806
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ImageEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
12807
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.5", type: ImageEditor, isStandalone: true, selector: "kj-rte-image-editor", viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, isSignal: true }], ngImport: i0, template: `
12808
+ <form class="kj-rte__overlay-form" (submit)="onInsert($event)">
12809
+ <label class="kj-rte__overlay-label" for="kj-rte-image-src">Image URL</label>
12810
+ <input
12811
+ #input
12812
+ id="kj-rte-image-src"
12813
+ class="kj-rte__overlay-input"
12814
+ type="url"
12815
+ placeholder="https://example.com/photo.jpg"
12816
+ [value]="src()"
12817
+ (input)="src.set($any($event.target).value)"
12818
+ (keydown.escape)="data.close()"
12819
+ />
12820
+ <label class="kj-rte__overlay-label" for="kj-rte-image-alt">Alt text</label>
12821
+ <input
12822
+ id="kj-rte-image-alt"
12823
+ class="kj-rte__overlay-input"
12824
+ type="text"
12825
+ placeholder="Describe the image"
12826
+ [value]="alt()"
12827
+ (input)="alt.set($any($event.target).value)"
12828
+ (keydown.escape)="data.close()"
12829
+ />
12830
+ <div class="kj-rte__overlay-actions">
12831
+ <button type="submit" class="kj-rte__overlay-btn" [disabled]="!src().trim()">Insert</button>
12832
+ <button type="button" class="kj-rte__overlay-btn" (click)="data.close()">Cancel</button>
12833
+ </div>
12834
+ </form>
12835
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
12836
+ }
12837
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: ImageEditor, decorators: [{
12838
+ type: Component,
12839
+ args: [{
12840
+ selector: 'kj-rte-image-editor',
12841
+ standalone: true,
12842
+ template: `
12843
+ <form class="kj-rte__overlay-form" (submit)="onInsert($event)">
12844
+ <label class="kj-rte__overlay-label" for="kj-rte-image-src">Image URL</label>
12845
+ <input
12846
+ #input
12847
+ id="kj-rte-image-src"
12848
+ class="kj-rte__overlay-input"
12849
+ type="url"
12850
+ placeholder="https://example.com/photo.jpg"
12851
+ [value]="src()"
12852
+ (input)="src.set($any($event.target).value)"
12853
+ (keydown.escape)="data.close()"
12854
+ />
12855
+ <label class="kj-rte__overlay-label" for="kj-rte-image-alt">Alt text</label>
12856
+ <input
12857
+ id="kj-rte-image-alt"
12858
+ class="kj-rte__overlay-input"
12859
+ type="text"
12860
+ placeholder="Describe the image"
12861
+ [value]="alt()"
12862
+ (input)="alt.set($any($event.target).value)"
12863
+ (keydown.escape)="data.close()"
12864
+ />
12865
+ <div class="kj-rte__overlay-actions">
12866
+ <button type="submit" class="kj-rte__overlay-btn" [disabled]="!src().trim()">Insert</button>
12867
+ <button type="button" class="kj-rte__overlay-btn" (click)="data.close()">Cancel</button>
12868
+ </div>
12869
+ </form>
12870
+ `,
12871
+ changeDetection: ChangeDetectionStrategy.OnPush,
12872
+ }]
12873
+ }], ctorParameters: () => [], propDecorators: { input: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }] } });
12874
+
12875
+ /**
12876
+ * Image feature. Lazily loads core `lexical` and builds a self-rendering image
12877
+ * node via `createKjImageNode`. Contributes a toolbar button + the image-editor
12878
+ * overlay (which collects URL + alt text).
12879
+ */
12880
+ function image() {
12881
+ let api;
12882
+ return {
12883
+ name: 'image',
12884
+ async load() {
12885
+ const lex = await import('lexical');
12886
+ api = createKjImageNode(lex);
12887
+ },
12888
+ nodes: () => [api.Node],
12889
+ toolbar: [
12890
+ {
12891
+ id: 'image',
12892
+ group: 'insert',
12893
+ order: 10,
12894
+ icon: 'image',
12895
+ label: 'Image',
12896
+ kind: 'button',
12897
+ run: (ctx) => ctx.openOverlay('image', {
12898
+ insert: (src, alt) => {
12899
+ ctx.insertNodes(() => [api.$create({ src, alt })]);
12900
+ ctx.closeOverlay();
12901
+ ctx.focus();
12902
+ ctx.announce('Image inserted');
12903
+ },
12904
+ close: () => {
12905
+ ctx.closeOverlay();
12906
+ ctx.focus();
12907
+ },
12908
+ }),
12909
+ },
12910
+ ],
12911
+ overlay: [{ id: 'image', label: 'Insert image', component: ImageEditor }],
12912
+ };
12913
+ }
12914
+
12915
+ /**
12916
+ * Markdown shortcuts (`# `, `- `, `1. `, `> `, `` ``` ``, `**bold**`, …). Lazily
12917
+ * loads `@lexical/markdown`. No toolbar UI — it's a typing behaviour.
12918
+ */
12919
+ function markdownShortcuts() {
12920
+ let mod;
12921
+ return {
12922
+ name: 'markdown-shortcuts',
12923
+ async load() {
12924
+ mod = await import('@lexical/markdown');
12925
+ },
12926
+ setup: (ctx) => mod.registerMarkdownShortcuts(ctx.editor, mod.TRANSFORMERS),
12927
+ };
12928
+ }
12929
+
12930
+ /**
12931
+ * Undo/redo history. Lazily loads `@lexical/history` and contributes undo/redo
12932
+ * toolbar buttons (disabled until the respective action is available).
12933
+ */
12934
+ function history() {
12935
+ let mod;
12936
+ return {
12937
+ name: 'history',
12938
+ async load() {
12939
+ mod = await import('@lexical/history');
12940
+ },
12941
+ setup: (ctx) => mod.registerHistory(ctx.editor, mod.createEmptyHistoryState(), 300),
12942
+ toolbar: [
12943
+ {
12944
+ id: 'undo',
12945
+ group: 'history',
12946
+ order: 0,
12947
+ icon: 'undo',
12948
+ label: 'Undo',
12949
+ ariaKeyshortcuts: 'Control+Z',
12950
+ kind: 'button',
12951
+ isDisabled: (state) => !state.canUndo,
12952
+ run: (ctx) => ctx.undo(),
12953
+ },
12954
+ {
12955
+ id: 'redo',
12956
+ group: 'history',
12957
+ order: 1,
12958
+ icon: 'redo',
12959
+ label: 'Redo',
12960
+ ariaKeyshortcuts: 'Control+Shift+Z',
12961
+ kind: 'button',
12962
+ isDisabled: (state) => !state.canRedo,
12963
+ run: (ctx) => ctx.redo(),
12964
+ },
12965
+ ],
12966
+ };
12967
+ }
12968
+
12969
+ /**
12970
+ * The full default feature bundle, so a zero-config `<kj-rich-text-editor>`
12971
+ * still gives a complete editor. Compose your own subset with the individual
12972
+ * factories to load only the packages you need.
12973
+ */
12974
+ function defaultFeatures() {
12975
+ return [
12976
+ bold(),
12977
+ italic(),
12978
+ underline(),
12979
+ strike(),
12980
+ inlineCode(),
12981
+ heading(),
12982
+ bulletList(),
12983
+ orderedList(),
12984
+ quote(),
12985
+ codeBlock(),
12986
+ link(),
12987
+ image(),
12988
+ markdownShortcuts(),
12989
+ history(),
12990
+ ];
12991
+ }
12992
+
12993
+ let kjRteUid = 0;
12994
+ /**
12995
+ * Styled, accessible rich-text editor composing the headless
12996
+ * {@link KjRichTextEditor} core directive with a **dynamic** `role="toolbar"`
12997
+ * that renders whatever the active features contribute (sorted by group then
12998
+ * order) — no hardcoded buttons. Feature overlays (link/image editors) render in
12999
+ * an accessible `role="dialog"` popover.
13000
+ *
13001
+ * Zero-config gives the full editor via {@link defaultFeatures}; pass a subset to
13002
+ * `kjFeatures` (or `provideKjRichText(...)`) to load only the packages you need.
13003
+ *
13004
+ * @example
13005
+ * ```html
13006
+ * <kj-rich-text-editor kjLabel="Message" [(kjValue)]="html" />
13007
+ * <kj-rich-text-editor [kjFeatures]="[bold(), italic(), link()]" />
13008
+ * ```
13009
+ * @doc-category Library/Forms
13010
+ * @doc
13011
+ * @doc-name rich-text-editor
13012
+ * @doc-is-main
13013
+ * @doc-description Accessible, feature-composed rich-text editor wrapping Lexical with a dynamic toolbar.
13014
+ * @doc-example Default [full]
13015
+ * The full editor: the toolbar renders every default feature's contribution.
13016
+ * @doc-file rich-text-editor.example.ts
13017
+ * @doc-example Minimal (subset of features) [full]
13018
+ * Only bold, italic and link — the toolbar and loaded packages shrink to match.
13019
+ * @doc-file rich-text-editor.minimal.example.ts
13020
+ * @doc-example Custom feature [full]
13021
+ * A feature contributing its own toolbar button + node in a few lines.
13022
+ * @doc-file rich-text-editor.custom-node.example.ts
13023
+ * @doc-example Readonly [full]
13024
+ * Renders existing content without editing affordances.
13025
+ * @doc-file rich-text-editor.readonly.example.ts
13026
+ * @doc-aria role="textbox" — the editable surface, with aria-multiline="true".
13027
+ * @doc-aria role="toolbar" — the formatting controls, arrow-key navigable.
13028
+ * @doc-a11y Toggle items expose aria-pressed; feature actions announce via an aria-live region.
13029
+ * @doc-css-var --kj-rte-bg — Editor background.
13030
+ * @doc-css-var --kj-rte-border-color — Border colour.
13031
+ * @doc-css-var --kj-rte-radius — Corner radius.
13032
+ * @doc-css-var --kj-rte-min-height — Minimum height of the editable area.
13033
+ * @doc-related input,form,field
13034
+ */
13035
+ class KjRichTextEditorComponent {
13036
+ env = inject(EnvironmentInjector);
13037
+ /** Active features. Defaults to the full {@link defaultFeatures} bundle. */
13038
+ kjFeatures = input(defaultFeatures(), /* @ts-ignore */
13039
+ ...(ngDevMode ? [{ debugName: "kjFeatures" }] : /* istanbul ignore next */ []));
13040
+ /** Initial HTML content. */
13041
+ kjValue = input('', /* @ts-ignore */
13042
+ ...(ngDevMode ? [{ debugName: "kjValue" }] : /* istanbul ignore next */ []));
13043
+ /** Accessible label for the editable region (ignored when `kjLabelledBy` is set). */
13044
+ kjLabel = input('Rich text editor', /* @ts-ignore */
13045
+ ...(ngDevMode ? [{ debugName: "kjLabel" }] : /* istanbul ignore next */ []));
13046
+ /** ID of an external element that labels the editable region. */
13047
+ kjLabelledBy = input('', /* @ts-ignore */
13048
+ ...(ngDevMode ? [{ debugName: "kjLabelledBy" }] : /* istanbul ignore next */ []));
13049
+ /** Placeholder shown while the editor is empty. */
13050
+ kjPlaceholder = input('', /* @ts-ignore */
13051
+ ...(ngDevMode ? [{ debugName: "kjPlaceholder" }] : /* istanbul ignore next */ []));
13052
+ /** Render read-only (non-editable) content. */
13053
+ kjReadonly = input(false, /* @ts-ignore */
13054
+ ...(ngDevMode ? [{ debugName: "kjReadonly" }] : /* istanbul ignore next */ []));
13055
+ /** Accessible label for the toolbar. */
13056
+ kjToolbarLabel = input('Formatting', /* @ts-ignore */
13057
+ ...(ngDevMode ? [{ debugName: "kjToolbarLabel" }] : /* istanbul ignore next */ []));
13058
+ /** Whether the formatting toolbar is shown. */
13059
+ kjShowToolbar = input(true, /* @ts-ignore */
13060
+ ...(ngDevMode ? [{ debugName: "kjShowToolbar" }] : /* istanbul ignore next */ []));
13061
+ /** Emits the serialized HTML whenever the content changes. */
13062
+ valueChange = output();
13063
+ /** Emits the plain text whenever the content changes. */
13064
+ textChange = output();
13065
+ /** Emits the Lexical serialized state whenever the content changes. */
13066
+ jsonChange = output();
13067
+ /** @internal Stable id used for aria-controls / labelledby wiring. */
13068
+ contentId = `kj-rte-${kjRteUid++}`;
13069
+ live = viewChild(KjLiveRegion, /* @ts-ignore */
13070
+ ...(ngDevMode ? [{ debugName: "live" }] : /* istanbul ignore next */ []));
13071
+ overlayInjectors = new WeakMap();
13072
+ /** Run a toolbar item and announce toggle state changes to AT. */
13073
+ onRun(ed, item) {
13074
+ ed.runItem(item);
13075
+ if (item.kind === 'toggle') {
13076
+ this.announce(`${item.label} ${ed.itemActive(item) ? 'on' : 'off'}`);
13077
+ }
13078
+ }
13079
+ /** Announce a message via the live region (also handles feature announcements). */
13080
+ announce(message) {
13081
+ this.live()?.announce(message);
13082
+ }
13083
+ /** Injector that exposes the overlay's data via KJ_RTE_OVERLAY_DATA. */
13084
+ overlayInjector(active) {
13085
+ const key = (active.data ?? active);
13086
+ let injector = this.overlayInjectors.get(key);
13087
+ if (!injector) {
13088
+ injector = Injector.create({
13089
+ parent: this.env,
13090
+ providers: [{ provide: KJ_RTE_OVERLAY_DATA, useValue: active.data }],
13091
+ });
13092
+ this.overlayInjectors.set(key, injector);
13093
+ }
13094
+ return injector;
13095
+ }
13096
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjRichTextEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13097
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjRichTextEditorComponent, isStandalone: true, selector: "kj-rich-text-editor", inputs: { kjFeatures: { classPropertyName: "kjFeatures", publicName: "kjFeatures", isSignal: true, isRequired: false, transformFunction: null }, kjValue: { classPropertyName: "kjValue", publicName: "kjValue", isSignal: true, isRequired: false, transformFunction: null }, kjLabel: { classPropertyName: "kjLabel", publicName: "kjLabel", isSignal: true, isRequired: false, transformFunction: null }, kjLabelledBy: { classPropertyName: "kjLabelledBy", publicName: "kjLabelledBy", isSignal: true, isRequired: false, transformFunction: null }, kjPlaceholder: { classPropertyName: "kjPlaceholder", publicName: "kjPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, kjReadonly: { classPropertyName: "kjReadonly", publicName: "kjReadonly", isSignal: true, isRequired: false, transformFunction: null }, kjToolbarLabel: { classPropertyName: "kjToolbarLabel", publicName: "kjToolbarLabel", isSignal: true, isRequired: false, transformFunction: null }, kjShowToolbar: { classPropertyName: "kjShowToolbar", publicName: "kjShowToolbar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", textChange: "textChange", jsonChange: "jsonChange" }, host: { classAttribute: "kj-rte" }, viewQueries: [{ propertyName: "live", first: true, predicate: KjLiveRegion, descendants: true, isSignal: true }], ngImport: i0, template: `
13098
+ @if (kjShowToolbar()) {
13099
+ <div
13100
+ class="kj-rte__toolbar"
13101
+ role="toolbar"
13102
+ [attr.aria-label]="kjToolbarLabel()"
13103
+ [attr.aria-controls]="contentId"
13104
+ kjRovingTabindex
13105
+ kjRovingOrientation="horizontal"
13106
+ >
13107
+ @for (grp of ed.toolbarGroups(); track grp.group; let firstGroup = $first) {
13108
+ @if (!firstGroup) {
13109
+ <span class="kj-rte__sep" role="separator" aria-orientation="vertical"></span>
13110
+ }
13111
+ <div class="kj-rte__group" role="group" [attr.aria-label]="grp.group">
13112
+ @for (item of grp.items; track item.id) {
13113
+ <button
13114
+ type="button"
13115
+ class="kj-rte__btn"
13116
+ kjRovingTabindexItem
13117
+ [attr.aria-label]="item.label"
13118
+ [title]="item.label"
13119
+ [attr.aria-keyshortcuts]="item.ariaKeyshortcuts || null"
13120
+ [class.kj-rte__btn--active]="ed.itemActive(item)"
13121
+ [attr.aria-pressed]="item.kind === 'toggle' ? ed.itemActive(item) : null"
13122
+ [disabled]="ed.itemDisabled(item)"
13123
+ (mousedown)="$event.preventDefault()"
13124
+ (click)="onRun(ed, item)"
13125
+ >
13126
+ <i [kjIcon]="item.icon" aria-hidden="true"></i>
13127
+ </button>
13128
+ }
13129
+ </div>
13130
+ }
13131
+ </div>
13132
+
13133
+ @if (ed.activeOverlay(); as ov) {
13134
+ <div class="kj-rte__overlay" role="dialog" [attr.aria-label]="ov.overlay.label">
13135
+ <ng-container
13136
+ *ngComponentOutlet="ov.overlay.component; injector: overlayInjector(ov)"
13137
+ />
13138
+ </div>
13139
+ }
13140
+ }
13141
+
13142
+ <div
13143
+ #ed="kjRichTextEditor"
13144
+ [id]="contentId"
13145
+ class="kj-rte__content"
13146
+ kjRichTextEditor
13147
+ [kjFeatures]="kjFeatures()"
13148
+ [kjValue]="kjValue()"
13149
+ [kjReadonly]="kjReadonly()"
13150
+ [attr.aria-label]="kjLabelledBy() ? null : kjLabel()"
13151
+ [attr.aria-labelledby]="kjLabelledBy() || null"
13152
+ [attr.data-placeholder]="kjPlaceholder() || null"
13153
+ (valueChange)="valueChange.emit($event)"
13154
+ (textChange)="textChange.emit($event)"
13155
+ (jsonChange)="jsonChange.emit($event)"
13156
+ (announce)="announce($event)"
13157
+ ></div>
13158
+
13159
+ <div class="kj-rte__sr" kjLiveRegion aria-live="polite"></div>
13160
+ `, isInline: true, styles: ["@layer kj.component{.kj-rte{--kj-rte-bg: var(--kj-bg-field);--kj-rte-fg: var(--kj-fg-default);--kj-rte-muted-fg: var(--kj-fg-muted);--kj-rte-border-color: var(--kj-border-default);--kj-rte-radius: var(--kj-radius-field);--kj-rte-toolbar-bg: var(--kj-bg-surface, var(--kj-bg-body));--kj-rte-btn-size: 2.75rem;--kj-rte-accent: var(--kj-bg-primary);--kj-rte-accent-fg: var(--kj-fg-on-primary);--kj-rte-min-height: 12rem;--kj-rte-pad: var(--kj-space-md);--kj-rte-font: var(--kj-font-sans);--kj-rte-mono: var(--kj-font-mono, ui-monospace, monospace);display:flex;flex-direction:column;width:100%;max-width:100%;min-width:0;box-sizing:border-box;background:var(--kj-rte-bg);color:var(--kj-rte-fg);border:var(--kj-border) solid var(--kj-rte-border-color);border-radius:var(--kj-rte-radius);font-family:var(--kj-rte-font);overflow:hidden}.kj-rte:focus-within{outline:2px solid var(--kj-rte-accent);outline-offset:1px;border-color:var(--kj-border-focus, var(--kj-rte-accent))}.kj-rte__toolbar{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--kj-space-xs, .25rem);padding:var(--kj-space-sm);background:var(--kj-rte-toolbar-bg);border-bottom:var(--kj-border) solid var(--kj-rte-border-color);overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:var(--kj-rte-border-color) transparent}.kj-rte__toolbar::-webkit-scrollbar{height:.5rem}.kj-rte__toolbar::-webkit-scrollbar-thumb{background:var(--kj-rte-border-color);border-radius:.25rem}.kj-rte__toolbar::-webkit-scrollbar-track{background:transparent}.kj-rte__group{display:flex;align-items:center;gap:var(--kj-space-xs, .25rem)}.kj-rte__group,.kj-rte__sep,.kj-rte__btn{flex:0 0 auto}.kj-rte__sep{width:1px;align-self:stretch;min-height:1.5rem;margin:0 var(--kj-space-xs, .25rem);background:var(--kj-rte-border-color)}.kj-rte__btn{display:inline-flex;align-items:center;justify-content:center;min-width:var(--kj-rte-btn-size);min-height:var(--kj-rte-btn-size);padding:0 var(--kj-space-sm);color:var(--kj-rte-fg);background:transparent;border:var(--kj-border) solid transparent;border-radius:var(--kj-radius-field);cursor:pointer;transition:var(--kj-transition, background-color .15s ease, color .15s ease)}.kj-rte__btn:hover:not(:disabled){background:var(--kj-bg-subtle, var(--kj-bg-body))}.kj-rte__btn:focus-visible{outline:2px solid var(--kj-rte-accent);outline-offset:2px}.kj-rte__btn--active{background:color-mix(in srgb,var(--kj-rte-accent) 16%,transparent);border-color:color-mix(in srgb,var(--kj-rte-accent) 40%,transparent);color:var(--kj-rte-accent)}.kj-rte__btn:disabled{opacity:.45;cursor:not-allowed}.kj-rte__overlay{position:relative;z-index:1;padding:var(--kj-space-sm) var(--kj-rte-pad);background:var(--kj-rte-toolbar-bg);border-bottom:var(--kj-border) solid var(--kj-rte-border-color);box-shadow:0 6px 16px #0000001f}.kj-rte__overlay-form{display:flex;flex-wrap:wrap;align-items:center;gap:var(--kj-space-sm)}.kj-rte__overlay-label{font-size:var(--kj-text-sm);color:var(--kj-rte-muted-fg)}.kj-rte__overlay-input{flex:1 1 12rem;min-height:2.25rem;padding:var(--kj-space-sm) var(--kj-space-md);color:var(--kj-rte-fg);background:var(--kj-bg-field);border:var(--kj-border) solid var(--kj-rte-border-color);border-radius:var(--kj-radius-field);font:var(--kj-text-sm) / 1.4 var(--kj-rte-font)}.kj-rte__overlay-input:focus-visible{outline:2px solid var(--kj-rte-accent);outline-offset:1px}.kj-rte__overlay-actions{display:flex;gap:var(--kj-space-sm)}.kj-rte__overlay-btn{min-height:2.25rem;padding:0 var(--kj-space-md);color:var(--kj-rte-fg);background:transparent;border:var(--kj-border) solid var(--kj-rte-border-color);border-radius:var(--kj-radius-field);cursor:pointer}.kj-rte__overlay-btn:hover:not(:disabled){background:var(--kj-bg-subtle, var(--kj-bg-body))}.kj-rte__overlay-btn:focus-visible{outline:2px solid var(--kj-rte-accent);outline-offset:2px}.kj-rte__overlay-btn:disabled{opacity:.45;cursor:not-allowed}.kj-rte__content{flex:1 1 auto;min-width:0;min-height:var(--kj-rte-min-height);padding:var(--kj-rte-pad);outline:none;overflow-y:auto;overflow-wrap:anywhere;line-height:1.6;color:var(--kj-rte-fg)}.kj-rte__content[data-empty][data-placeholder]:before{content:attr(data-placeholder);color:var(--kj-rte-muted-fg);pointer-events:none}.kj-rte__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-rte .kj-rte-paragraph{margin:0 0 var(--kj-space-sm)}.kj-rte .kj-rte-h1{margin:0 0 var(--kj-space-sm);font-size:var(--kj-text-2xl, 1.75rem);font-weight:700;line-height:1.25}.kj-rte .kj-rte-h2{margin:0 0 var(--kj-space-sm);font-size:var(--kj-text-xl, 1.4rem);font-weight:700;line-height:1.3}.kj-rte .kj-rte-h3{margin:0 0 var(--kj-space-sm);font-size:var(--kj-text-lg, 1.2rem);font-weight:600;line-height:1.35}.kj-rte .kj-rte-ul,.kj-rte .kj-rte-ol{margin:0 0 var(--kj-space-sm);padding-left:1.5rem}.kj-rte .kj-rte-ul{list-style:disc}.kj-rte .kj-rte-ol{list-style:decimal}.kj-rte .kj-rte-li{margin-bottom:.25rem}.kj-rte .kj-rte-quote{margin:0 0 var(--kj-space-sm);padding-left:var(--kj-space-md);border-left:3px solid var(--kj-rte-border-color);color:var(--kj-rte-muted-fg);font-style:italic}.kj-rte .kj-rte-link{color:var(--kj-rte-accent);text-decoration:underline;text-underline-offset:2px}.kj-rte .kj-rte-bold{font-weight:700}.kj-rte .kj-rte-italic{font-style:italic}.kj-rte .kj-rte-underline{text-decoration:underline}.kj-rte .kj-rte-strikethrough{text-decoration:line-through}.kj-rte .kj-rte-code{padding:.1em .35em;background:var(--kj-bg-subtle, var(--kj-bg-body));border-radius:.25rem;font-family:var(--kj-rte-mono);font-size:.9em}.kj-rte .kj-rte-code-block{display:block;margin:0 0 var(--kj-space-sm);padding:var(--kj-space-md);background:var(--kj-bg-subtle, var(--kj-bg-body));border-radius:var(--kj-radius-field);font-family:var(--kj-rte-mono);font-size:.9em;white-space:pre-wrap;overflow-x:auto}.kj-rte .kj-rte-image{margin:var(--kj-space-sm) 0}.kj-rte .kj-rte-image img{max-width:100%;height:auto;border-radius:var(--kj-radius-field)}@media(prefers-reduced-motion:reduce){.kj-rte__btn,.kj-rte{transition:none}}}\n"], dependencies: [{ kind: "directive", type: KjRichTextEditor, selector: "[kjRichTextEditor]", inputs: ["kjValue", "kjFeatures", "kjExtensions", "kjPlugins", "kjReadonly", "kjSpellcheck", "kjNamespace"], outputs: ["valueChange", "textChange", "jsonChange", "announce"], exportAs: ["kjRichTextEditor"] }, { kind: "directive", type: KjRovingTabindex, selector: "[kjRovingTabindex]", inputs: ["kjRovingOrientation"] }, { kind: "directive", type: KjRovingTabindexItemDirective, selector: "[kjRovingTabindexItem]" }, { kind: "directive", type: KjLiveRegion, selector: "[kjLiveRegion]", inputs: ["kjPoliteness"], exportAs: ["kjLiveRegion"] }, { kind: "directive", type: KjIconDirective, selector: "span[kjIcon], i[kjIcon]", inputs: ["kjIcon", "kjIconLabel", "kjIconColor", "kjIconSize"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13161
+ }
13162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjRichTextEditorComponent, decorators: [{
13163
+ type: Component,
13164
+ args: [{ selector: 'kj-rich-text-editor', standalone: true, imports: [
13165
+ KjRichTextEditor,
13166
+ KjRovingTabindex,
13167
+ KjRovingTabindexItemDirective,
13168
+ KjLiveRegion,
13169
+ KjIconDirective,
13170
+ NgComponentOutlet,
13171
+ ], host: { class: 'kj-rte' }, template: `
13172
+ @if (kjShowToolbar()) {
13173
+ <div
13174
+ class="kj-rte__toolbar"
13175
+ role="toolbar"
13176
+ [attr.aria-label]="kjToolbarLabel()"
13177
+ [attr.aria-controls]="contentId"
13178
+ kjRovingTabindex
13179
+ kjRovingOrientation="horizontal"
13180
+ >
13181
+ @for (grp of ed.toolbarGroups(); track grp.group; let firstGroup = $first) {
13182
+ @if (!firstGroup) {
13183
+ <span class="kj-rte__sep" role="separator" aria-orientation="vertical"></span>
13184
+ }
13185
+ <div class="kj-rte__group" role="group" [attr.aria-label]="grp.group">
13186
+ @for (item of grp.items; track item.id) {
13187
+ <button
13188
+ type="button"
13189
+ class="kj-rte__btn"
13190
+ kjRovingTabindexItem
13191
+ [attr.aria-label]="item.label"
13192
+ [title]="item.label"
13193
+ [attr.aria-keyshortcuts]="item.ariaKeyshortcuts || null"
13194
+ [class.kj-rte__btn--active]="ed.itemActive(item)"
13195
+ [attr.aria-pressed]="item.kind === 'toggle' ? ed.itemActive(item) : null"
13196
+ [disabled]="ed.itemDisabled(item)"
13197
+ (mousedown)="$event.preventDefault()"
13198
+ (click)="onRun(ed, item)"
13199
+ >
13200
+ <i [kjIcon]="item.icon" aria-hidden="true"></i>
13201
+ </button>
13202
+ }
13203
+ </div>
13204
+ }
13205
+ </div>
13206
+
13207
+ @if (ed.activeOverlay(); as ov) {
13208
+ <div class="kj-rte__overlay" role="dialog" [attr.aria-label]="ov.overlay.label">
13209
+ <ng-container
13210
+ *ngComponentOutlet="ov.overlay.component; injector: overlayInjector(ov)"
13211
+ />
13212
+ </div>
13213
+ }
13214
+ }
13215
+
13216
+ <div
13217
+ #ed="kjRichTextEditor"
13218
+ [id]="contentId"
13219
+ class="kj-rte__content"
13220
+ kjRichTextEditor
13221
+ [kjFeatures]="kjFeatures()"
13222
+ [kjValue]="kjValue()"
13223
+ [kjReadonly]="kjReadonly()"
13224
+ [attr.aria-label]="kjLabelledBy() ? null : kjLabel()"
13225
+ [attr.aria-labelledby]="kjLabelledBy() || null"
13226
+ [attr.data-placeholder]="kjPlaceholder() || null"
13227
+ (valueChange)="valueChange.emit($event)"
13228
+ (textChange)="textChange.emit($event)"
13229
+ (jsonChange)="jsonChange.emit($event)"
13230
+ (announce)="announce($event)"
13231
+ ></div>
13232
+
13233
+ <div class="kj-rte__sr" kjLiveRegion aria-live="polite"></div>
13234
+ `, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-rte{--kj-rte-bg: var(--kj-bg-field);--kj-rte-fg: var(--kj-fg-default);--kj-rte-muted-fg: var(--kj-fg-muted);--kj-rte-border-color: var(--kj-border-default);--kj-rte-radius: var(--kj-radius-field);--kj-rte-toolbar-bg: var(--kj-bg-surface, var(--kj-bg-body));--kj-rte-btn-size: 2.75rem;--kj-rte-accent: var(--kj-bg-primary);--kj-rte-accent-fg: var(--kj-fg-on-primary);--kj-rte-min-height: 12rem;--kj-rte-pad: var(--kj-space-md);--kj-rte-font: var(--kj-font-sans);--kj-rte-mono: var(--kj-font-mono, ui-monospace, monospace);display:flex;flex-direction:column;width:100%;max-width:100%;min-width:0;box-sizing:border-box;background:var(--kj-rte-bg);color:var(--kj-rte-fg);border:var(--kj-border) solid var(--kj-rte-border-color);border-radius:var(--kj-rte-radius);font-family:var(--kj-rte-font);overflow:hidden}.kj-rte:focus-within{outline:2px solid var(--kj-rte-accent);outline-offset:1px;border-color:var(--kj-border-focus, var(--kj-rte-accent))}.kj-rte__toolbar{display:flex;flex-wrap:nowrap;align-items:center;gap:var(--kj-space-xs, .25rem);padding:var(--kj-space-sm);background:var(--kj-rte-toolbar-bg);border-bottom:var(--kj-border) solid var(--kj-rte-border-color);overflow-x:auto;overflow-y:hidden;scrollbar-width:thin;scrollbar-color:var(--kj-rte-border-color) transparent}.kj-rte__toolbar::-webkit-scrollbar{height:.5rem}.kj-rte__toolbar::-webkit-scrollbar-thumb{background:var(--kj-rte-border-color);border-radius:.25rem}.kj-rte__toolbar::-webkit-scrollbar-track{background:transparent}.kj-rte__group{display:flex;align-items:center;gap:var(--kj-space-xs, .25rem)}.kj-rte__group,.kj-rte__sep,.kj-rte__btn{flex:0 0 auto}.kj-rte__sep{width:1px;align-self:stretch;min-height:1.5rem;margin:0 var(--kj-space-xs, .25rem);background:var(--kj-rte-border-color)}.kj-rte__btn{display:inline-flex;align-items:center;justify-content:center;min-width:var(--kj-rte-btn-size);min-height:var(--kj-rte-btn-size);padding:0 var(--kj-space-sm);color:var(--kj-rte-fg);background:transparent;border:var(--kj-border) solid transparent;border-radius:var(--kj-radius-field);cursor:pointer;transition:var(--kj-transition, background-color .15s ease, color .15s ease)}.kj-rte__btn:hover:not(:disabled){background:var(--kj-bg-subtle, var(--kj-bg-body))}.kj-rte__btn:focus-visible{outline:2px solid var(--kj-rte-accent);outline-offset:2px}.kj-rte__btn--active{background:color-mix(in srgb,var(--kj-rte-accent) 16%,transparent);border-color:color-mix(in srgb,var(--kj-rte-accent) 40%,transparent);color:var(--kj-rte-accent)}.kj-rte__btn:disabled{opacity:.45;cursor:not-allowed}.kj-rte__overlay{position:relative;z-index:1;padding:var(--kj-space-sm) var(--kj-rte-pad);background:var(--kj-rte-toolbar-bg);border-bottom:var(--kj-border) solid var(--kj-rte-border-color);box-shadow:0 6px 16px #0000001f}.kj-rte__overlay-form{display:flex;flex-wrap:wrap;align-items:center;gap:var(--kj-space-sm)}.kj-rte__overlay-label{font-size:var(--kj-text-sm);color:var(--kj-rte-muted-fg)}.kj-rte__overlay-input{flex:1 1 12rem;min-height:2.25rem;padding:var(--kj-space-sm) var(--kj-space-md);color:var(--kj-rte-fg);background:var(--kj-bg-field);border:var(--kj-border) solid var(--kj-rte-border-color);border-radius:var(--kj-radius-field);font:var(--kj-text-sm) / 1.4 var(--kj-rte-font)}.kj-rte__overlay-input:focus-visible{outline:2px solid var(--kj-rte-accent);outline-offset:1px}.kj-rte__overlay-actions{display:flex;gap:var(--kj-space-sm)}.kj-rte__overlay-btn{min-height:2.25rem;padding:0 var(--kj-space-md);color:var(--kj-rte-fg);background:transparent;border:var(--kj-border) solid var(--kj-rte-border-color);border-radius:var(--kj-radius-field);cursor:pointer}.kj-rte__overlay-btn:hover:not(:disabled){background:var(--kj-bg-subtle, var(--kj-bg-body))}.kj-rte__overlay-btn:focus-visible{outline:2px solid var(--kj-rte-accent);outline-offset:2px}.kj-rte__overlay-btn:disabled{opacity:.45;cursor:not-allowed}.kj-rte__content{flex:1 1 auto;min-width:0;min-height:var(--kj-rte-min-height);padding:var(--kj-rte-pad);outline:none;overflow-y:auto;overflow-wrap:anywhere;line-height:1.6;color:var(--kj-rte-fg)}.kj-rte__content[data-empty][data-placeholder]:before{content:attr(data-placeholder);color:var(--kj-rte-muted-fg);pointer-events:none}.kj-rte__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.kj-rte .kj-rte-paragraph{margin:0 0 var(--kj-space-sm)}.kj-rte .kj-rte-h1{margin:0 0 var(--kj-space-sm);font-size:var(--kj-text-2xl, 1.75rem);font-weight:700;line-height:1.25}.kj-rte .kj-rte-h2{margin:0 0 var(--kj-space-sm);font-size:var(--kj-text-xl, 1.4rem);font-weight:700;line-height:1.3}.kj-rte .kj-rte-h3{margin:0 0 var(--kj-space-sm);font-size:var(--kj-text-lg, 1.2rem);font-weight:600;line-height:1.35}.kj-rte .kj-rte-ul,.kj-rte .kj-rte-ol{margin:0 0 var(--kj-space-sm);padding-left:1.5rem}.kj-rte .kj-rte-ul{list-style:disc}.kj-rte .kj-rte-ol{list-style:decimal}.kj-rte .kj-rte-li{margin-bottom:.25rem}.kj-rte .kj-rte-quote{margin:0 0 var(--kj-space-sm);padding-left:var(--kj-space-md);border-left:3px solid var(--kj-rte-border-color);color:var(--kj-rte-muted-fg);font-style:italic}.kj-rte .kj-rte-link{color:var(--kj-rte-accent);text-decoration:underline;text-underline-offset:2px}.kj-rte .kj-rte-bold{font-weight:700}.kj-rte .kj-rte-italic{font-style:italic}.kj-rte .kj-rte-underline{text-decoration:underline}.kj-rte .kj-rte-strikethrough{text-decoration:line-through}.kj-rte .kj-rte-code{padding:.1em .35em;background:var(--kj-bg-subtle, var(--kj-bg-body));border-radius:.25rem;font-family:var(--kj-rte-mono);font-size:.9em}.kj-rte .kj-rte-code-block{display:block;margin:0 0 var(--kj-space-sm);padding:var(--kj-space-md);background:var(--kj-bg-subtle, var(--kj-bg-body));border-radius:var(--kj-radius-field);font-family:var(--kj-rte-mono);font-size:.9em;white-space:pre-wrap;overflow-x:auto}.kj-rte .kj-rte-image{margin:var(--kj-space-sm) 0}.kj-rte .kj-rte-image img{max-width:100%;height:auto;border-radius:var(--kj-radius-field)}@media(prefers-reduced-motion:reduce){.kj-rte__btn,.kj-rte{transition:none}}}\n"] }]
13235
+ }], propDecorators: { kjFeatures: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjFeatures", required: false }] }], kjValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjValue", required: false }] }], kjLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLabel", required: false }] }], kjLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLabelledBy", required: false }] }], kjPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjPlaceholder", required: false }] }], kjReadonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjReadonly", required: false }] }], kjToolbarLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjToolbarLabel", required: false }] }], kjShowToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjShowToolbar", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], textChange: [{ type: i0.Output, args: ["textChange"] }], jsonChange: [{ type: i0.Output, args: ["jsonChange"] }], live: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KjLiveRegion), { isSignal: true }] }] } });
13236
+
10718
13237
  /**
10719
13238
  * Select root. Two-way bind via `[(value)]`.
10720
13239
  *
@@ -10896,6 +13415,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
10896
13415
  }]
10897
13416
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], kjLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLabel", required: false }] }] } });
10898
13417
 
13418
+ /**
13419
+ * Service-launched **bottom sheet** — a mobile-first, bottom-anchored modal
13420
+ * surface with a grab handle and drag-to-dismiss. Inject `KjSheetService` and
13421
+ * call `open()` with a body component; the sheet slides up from the bottom
13422
+ * edge, traps focus, and locks background scroll. It reuses the same overlay
13423
+ * primitive stack as the drawer and dialog — bottom sheet is the mobile
13424
+ * composition of that engine, not a new one. The wrapper component exists to
13425
+ * host this documentation page.
13426
+ *
13427
+ * @doc
13428
+ * @doc-name sheet
13429
+ * @doc-is-main
13430
+ * @doc-example Default
13431
+ * A service-launched bottom sheet with a grab handle and drag-to-dismiss.
13432
+ * @doc-file sheet.example.ts
13433
+ * @doc-example Detents
13434
+ * `detent` sets the initial resting height — auto / half / full.
13435
+ * @doc-file sheet.detents.example.ts
13436
+ * @doc-example Scrollable
13437
+ * A tall body scrolls inside the sheet while the grab handle stays pinned.
13438
+ * @doc-file sheet.scrollable.example.ts
13439
+ *
13440
+ * @doc-keyboard
13441
+ * Escape — Closes the sheet (only the topmost overlay when stacked)
13442
+ * Enter / Space — Dismisses when the grab handle is focused
13443
+ * Tab — Cycles focus within the sheet (focus trap via `tabCycle({ returnFocus: true })`)
13444
+ * Shift+Tab — Cycles backward
13445
+ *
13446
+ * @doc-aria
13447
+ * role — "dialog"; `aria-modal="true"` while the backdrop is active
13448
+ * aria-label — Set via the `ariaLabel` option when no heading is projected
13449
+ * aria-labelledby — Wire to the id of your sheet heading for the accessible name
13450
+ * data-state — "open" / "closed" — drives the slide-up transform
13451
+ * data-kj-detent — Mirrors the resolved initial height for theming hooks
13452
+ *
13453
+ * @doc-css-var
13454
+ * --kj-sheet-bg — Panel background fill. Defaults to --kj-bg-elevated.
13455
+ * --kj-sheet-fg — Foreground text color. Defaults to --kj-fg-default.
13456
+ * --kj-sheet-shadow — Box shadow off the panel. Defaults to --kj-shadow-lg.
13457
+ * --kj-sheet-radius — Top corner radius. Defaults to --kj-radius-box.
13458
+ * --kj-sheet-max-height — Cap on the sheet height. Defaults to 92vh.
13459
+ * --kj-sheet-grip-color — Grab-handle pill color. Defaults to --kj-border-strong.
13460
+ *
13461
+ * @doc-touch
13462
+ * The grab handle is a ≥ 44px-tall touch target (WCAG 2.5.5) even though the
13463
+ * visible grip pill is small. Downward drag past 40% of the sheet height (or
13464
+ * 600 px/s) dismisses. Footer action buttons should use `kj-button`
13465
+ * `size="lg"` (≥ 44px).
13466
+ *
13467
+ * @doc-a11y
13468
+ * Focus is trapped inside the sheet while open and returned to the triggering
13469
+ * element on close (`returnFocus: true`). Siblings outside the sheet are
13470
+ * marked `inert` while it is open. Stacking is safe — only the topmost overlay
13471
+ * receives Escape and outside-click. The wrapper does not generate an
13472
+ * accessible name; provide one via `aria-labelledby` (a visible heading) or
13473
+ * the `ariaLabel` option. Slide transitions respect
13474
+ * `prefers-reduced-motion`, falling back to an opacity fade.
13475
+ *
13476
+ * @doc-related drawer,dialog,action-sheet
13477
+ *
13478
+ * @doc-category Library/Overlay
13479
+ */
13480
+ class KjSheetComponent {
13481
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13482
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjSheetComponent, isStandalone: true, selector: "kj-sheet-shell", host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-sheet{--kj-sheet-bg: var(--kj-bg-elevated);--kj-sheet-fg: var(--kj-fg-default);--kj-sheet-shadow: var(--kj-shadow-lg);--kj-sheet-radius: var(--kj-radius-box);--kj-sheet-max-height: 92vh;--kj-sheet-grip-color: var(--kj-border-strong);position:fixed;left:0;right:0;bottom:0;display:flex;flex-direction:column;box-sizing:border-box;width:100%;max-height:var(--kj-sheet-max-height);margin-inline:auto;background:var(--kj-sheet-bg);color:var(--kj-sheet-fg);box-shadow:var(--kj-sheet-shadow);border-top-left-radius:var(--kj-sheet-radius);border-top-right-radius:var(--kj-sheet-radius);overflow:hidden;z-index:1000;transform:translate3d(0,var(--kj-sheet-drag-offset, 0),0);padding-bottom:env(safe-area-inset-bottom,0)}@media(min-width:40rem){.kj-sheet{max-width:32rem;border-bottom-left-radius:var(--kj-sheet-radius);border-bottom-right-radius:var(--kj-sheet-radius);bottom:var(--kj-space-lg)}}.kj-sheet[data-kj-detent=half]{height:50vh}.kj-sheet[data-kj-detent=full]{height:var(--kj-sheet-max-height)}.kj-sheet__handle{appearance:none;display:flex;align-items:center;justify-content:center;width:100%;min-height:44px;padding:0;border:0;background:transparent;cursor:grab;flex-shrink:0;touch-action:none}.kj-sheet[data-kj-dragging] .kj-sheet__handle{cursor:grabbing}.kj-sheet__grip{display:block;width:2.25rem;height:.3125rem;border-radius:999px;background:var(--kj-sheet-grip-color)}.kj-sheet__handle:focus-visible{outline:var(--kj-focus-ring-width, 2px) solid var(--kj-focus-ring-color, var(--kj-primary));outline-offset:-4px;border-radius:var(--kj-radius-sm)}.kj-sheet__content{flex:1;min-height:0;overflow-y:auto;padding:0 var(--kj-space-xl) var(--kj-space-xl);color:var(--kj-sheet-fg);font:.9375rem / 1.5 var(--kj-font-sans)}@media(prefers-reduced-motion:no-preference){.kj-sheet:not([data-kj-dragging]){transition:transform .26s cubic-bezier(.32,.72,0,1)}.kj-sheet[data-state=open]{transform:translate3d(0,var(--kj-sheet-drag-offset, 0),0)}.kj-sheet[data-state=closed]{transform:translate3d(0,100%,0)}}@media(prefers-reduced-motion:reduce){.kj-sheet:not([data-kj-dragging]){transition:opacity .12s linear}.kj-sheet[data-state=open]{opacity:1}.kj-sheet[data-state=closed]{opacity:0}}.kj-sheet__title{display:block;margin:0 0 var(--kj-space-xs);font:600 1.125rem / 1.3 var(--kj-font-sans);color:var(--kj-fg-default)}.kj-sheet__description{display:block;margin:0 0 var(--kj-space-md);color:var(--kj-fg-muted);font:.875rem / 1.4 var(--kj-font-sans)}.kj-sheet__footer{display:flex;gap:var(--kj-space-sm);padding-top:var(--kj-space-md)}.kj-sheet__footer[data-align=end]{justify-content:flex-end}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13483
+ }
13484
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSheetComponent, decorators: [{
13485
+ type: Component,
13486
+ args: [{ selector: 'kj-sheet-shell', standalone: true, template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-sheet{--kj-sheet-bg: var(--kj-bg-elevated);--kj-sheet-fg: var(--kj-fg-default);--kj-sheet-shadow: var(--kj-shadow-lg);--kj-sheet-radius: var(--kj-radius-box);--kj-sheet-max-height: 92vh;--kj-sheet-grip-color: var(--kj-border-strong);position:fixed;left:0;right:0;bottom:0;display:flex;flex-direction:column;box-sizing:border-box;width:100%;max-height:var(--kj-sheet-max-height);margin-inline:auto;background:var(--kj-sheet-bg);color:var(--kj-sheet-fg);box-shadow:var(--kj-sheet-shadow);border-top-left-radius:var(--kj-sheet-radius);border-top-right-radius:var(--kj-sheet-radius);overflow:hidden;z-index:1000;transform:translate3d(0,var(--kj-sheet-drag-offset, 0),0);padding-bottom:env(safe-area-inset-bottom,0)}@media(min-width:40rem){.kj-sheet{max-width:32rem;border-bottom-left-radius:var(--kj-sheet-radius);border-bottom-right-radius:var(--kj-sheet-radius);bottom:var(--kj-space-lg)}}.kj-sheet[data-kj-detent=half]{height:50vh}.kj-sheet[data-kj-detent=full]{height:var(--kj-sheet-max-height)}.kj-sheet__handle{appearance:none;display:flex;align-items:center;justify-content:center;width:100%;min-height:44px;padding:0;border:0;background:transparent;cursor:grab;flex-shrink:0;touch-action:none}.kj-sheet[data-kj-dragging] .kj-sheet__handle{cursor:grabbing}.kj-sheet__grip{display:block;width:2.25rem;height:.3125rem;border-radius:999px;background:var(--kj-sheet-grip-color)}.kj-sheet__handle:focus-visible{outline:var(--kj-focus-ring-width, 2px) solid var(--kj-focus-ring-color, var(--kj-primary));outline-offset:-4px;border-radius:var(--kj-radius-sm)}.kj-sheet__content{flex:1;min-height:0;overflow-y:auto;padding:0 var(--kj-space-xl) var(--kj-space-xl);color:var(--kj-sheet-fg);font:.9375rem / 1.5 var(--kj-font-sans)}@media(prefers-reduced-motion:no-preference){.kj-sheet:not([data-kj-dragging]){transition:transform .26s cubic-bezier(.32,.72,0,1)}.kj-sheet[data-state=open]{transform:translate3d(0,var(--kj-sheet-drag-offset, 0),0)}.kj-sheet[data-state=closed]{transform:translate3d(0,100%,0)}}@media(prefers-reduced-motion:reduce){.kj-sheet:not([data-kj-dragging]){transition:opacity .12s linear}.kj-sheet[data-state=open]{opacity:1}.kj-sheet[data-state=closed]{opacity:0}}.kj-sheet__title{display:block;margin:0 0 var(--kj-space-xs);font:600 1.125rem / 1.3 var(--kj-font-sans);color:var(--kj-fg-default)}.kj-sheet__description{display:block;margin:0 0 var(--kj-space-md);color:var(--kj-fg-muted);font:.875rem / 1.4 var(--kj-font-sans)}.kj-sheet__footer{display:flex;gap:var(--kj-space-sm);padding-top:var(--kj-space-md)}.kj-sheet__footer[data-align=end]{justify-content:flex-end}}\n"] }]
13487
+ }] });
13488
+
10899
13489
  /**
10900
13490
  * Styled wrapper around the headless `KjSkeleton` directive.
10901
13491
  *
@@ -11057,6 +13647,87 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
11057
13647
  }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-skeleton{--kj-skeleton-bg: var(--kj-bg-elevated, color-mix(in oklab, var(--kj-fg-default, #000) 12%, transparent));--kj-skeleton-highlight: var(--kj-bg-surface, color-mix(in oklab, var(--kj-fg-default, #000) 5%, transparent));--kj-skeleton-radius: var(--kj-radius-field, .375rem);--kj-skeleton-line-height: 1em;--kj-skeleton-line-radius: .25rem;--kj-skeleton-shimmer-duration: 1.4s;--kj-skeleton-pulse-duration: 1.6s;display:block;background-color:var(--kj-skeleton-bg);border-radius:var(--kj-skeleton-radius);inline-size:100%;block-size:1rem;overflow:hidden;position:relative}.kj-skeleton[data-shape=circle]{border-radius:50%;aspect-ratio:1 / 1}.kj-skeleton[data-shape=text],.kj-skeleton.kj-skeleton--line{block-size:var(--kj-skeleton-line-height);border-radius:var(--kj-skeleton-line-radius)}.kj-skeleton[data-shape=text-block]{display:flex;flex-direction:column;gap:var(--kj-space-sm, .5rem);background-color:transparent;border-radius:0;inline-size:100%;block-size:auto;overflow:visible}.kj-skeleton[data-animation=shimmer]:after{content:\"\";position:absolute;inset:0;background:linear-gradient(90deg,transparent 0%,var(--kj-skeleton-highlight) 50%,transparent 100%);transform:translate(-100%);animation:kj-skeleton-shimmer var(--kj-skeleton-shimmer-duration) linear infinite}.kj-skeleton[data-shape=text-block][data-animation=shimmer]:after{content:none}.kj-skeleton[data-animation=pulse]{animation:kj-skeleton-pulse var(--kj-skeleton-pulse-duration) ease-in-out infinite}.kj-skeleton[data-animation=none]:after{content:none}@keyframes kj-skeleton-shimmer{0%{transform:translate(-100%)}to{transform:translate(100%)}}@keyframes kj-skeleton-pulse{0%,to{opacity:1}50%{opacity:.55}}@media(prefers-reduced-motion:reduce){.kj-skeleton,.kj-skeleton:after{animation:none!important}}}\n"] }]
11058
13648
  }], propDecorators: { kjSkeletonShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSkeletonShape", required: false }] }], kjSkeletonAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSkeletonAnimation", required: false }] }], kjWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjWidth", required: false }] }], kjHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjHeight", required: false }] }], kjLines: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLines", required: false }] }] } });
11059
13649
 
13650
+ /**
13651
+ * Themed "skip to content" link — the styled wrapper around the headless
13652
+ * `KjSkipLink` directive. Implements [WCAG 2.4.1 Bypass
13653
+ * Blocks](https://www.w3.org/TR/WCAG21/#bypass-blocks): a keyboard user's first
13654
+ * Tab reveals it, and Enter jumps focus past the navbar / sidebar to the main
13655
+ * content landmark.
13656
+ *
13657
+ * Place it as the **first focusable element** of the app shell and give the main
13658
+ * landmark a matching `id` (default `main-content`):
13659
+ *
13660
+ * ```html
13661
+ * <kj-skip-link />
13662
+ * <kj-navbar />
13663
+ * <main id="main-content" tabindex="-1"><router-outlet /></main>
13664
+ * ```
13665
+ *
13666
+ * The visible label is projected content and defaults to "Skip to main content".
13667
+ * The link is visually hidden (parked above the viewport) until focused, then
13668
+ * slides into view with a solid high-contrast background so it is legible over
13669
+ * any page chrome.
13670
+ *
13671
+ * @example
13672
+ * ```html
13673
+ * <kj-skip-link />
13674
+ * <kj-skip-link kjTarget="page-body">Skip to article</kj-skip-link>
13675
+ * ```
13676
+ *
13677
+ * @doc-example Default
13678
+ * The shell-level skip link. Tab into the demo frame to reveal it, then
13679
+ * activate it to move focus to the demo's main region.
13680
+ * @doc-file skip-link.example.ts
13681
+ *
13682
+ * @doc-keyboard
13683
+ * Tab — Reveals the link when it receives focus (it is the first focusable element)
13684
+ * Enter — Activates it; keyboard focus moves to the target landmark
13685
+ *
13686
+ * @doc-aria
13687
+ * role=link — Native `<a>` semantics; accessible name from the projected label
13688
+ * href — Reflects `#<target>` so it works before hydration and is bookmarkable
13689
+ * tabindex=-1 — Applied to the target on activation so `focus()` lands and the
13690
+ * next Tab continues from the content, not the navigation
13691
+ *
13692
+ * @doc-a11y
13693
+ * Satisfies WCAG 2.4.1 Bypass Blocks. Hidden-until-focused (not
13694
+ * `display:none`, so it stays in the tab order), fully on-screen and
13695
+ * high-contrast when focused, and moves real keyboard focus — not just scroll.
13696
+ *
13697
+ * @doc-css-var
13698
+ * --kj-skip-link-bg — Background when focused. Defaults to the theme's primary surface.
13699
+ * --kj-skip-link-fg — Text color when focused. Pairs with the background for AAA contrast.
13700
+ * --kj-skip-link-radius — Corner radius of the focused pill.
13701
+ * --kj-skip-link-shadow — Elevation shadow when focused.
13702
+ * --kj-skip-link-offset — Inset from the top-left corner when focused.
13703
+ * --kj-skip-link-z — Stacking order. Must sit above the navbar and overlays.
13704
+ *
13705
+ * @doc-category Library/Navigation
13706
+ * @doc
13707
+ * @doc-name skip-link
13708
+ * @doc-description Themed, focus-moving "skip to main content" link for the app shell (WCAG 2.4.1).
13709
+ * @doc-is-main
13710
+ */
13711
+ class KjSkipLinkComponent {
13712
+ /** `id` of the main-content landmark to move focus to. Defaults to `'main-content'`. */
13713
+ kjTarget = input('main-content', /* @ts-ignore */
13714
+ ...(ngDevMode ? [{ debugName: "kjTarget" }] : /* istanbul ignore next */ []));
13715
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSkipLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13716
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: KjSkipLinkComponent, isStandalone: true, selector: "kj-skip-link", inputs: { kjTarget: { classPropertyName: "kjTarget", publicName: "kjTarget", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `
13717
+ <a kjSkipLink class="kj-skip-link" [kjSkipLink]="kjTarget()">
13718
+ <ng-content>Skip to main content</ng-content>
13719
+ </a>
13720
+ `, isInline: true, styles: ["@layer kj.component{.kj-skip-link{--kj-skip-link-bg: var(--kj-bg-primary);--kj-skip-link-fg: var(--kj-fg-on-primary);--kj-skip-link-radius: var(--kj-radius-field, .25rem);--kj-skip-link-shadow: var(--kj-shadow-lg);--kj-skip-link-offset: var(--kj-space-sm, .5rem);--kj-skip-link-z: 1000;position:fixed;top:0;left:var(--kj-skip-link-offset);z-index:var(--kj-skip-link-z);transform:translateY(-150%);transition:transform var(--kj-transition, .15s ease);display:inline-block;padding:.625rem 1rem;min-height:44px;box-sizing:border-box;background:var(--kj-skip-link-bg);color:var(--kj-skip-link-fg);border-radius:var(--kj-skip-link-radius);box-shadow:var(--kj-skip-link-shadow);font:inherit;font-weight:600;line-height:1.4;text-decoration:none;white-space:nowrap}.kj-skip-link:focus,.kj-skip-link:focus-visible{transform:translateY(var(--kj-skip-link-offset));outline:3px solid var(--kj-fg-primary);outline-offset:2px}@media(prefers-reduced-motion:reduce){.kj-skip-link{transition:none}}}\n"], dependencies: [{ kind: "directive", type: KjSkipLink, selector: "a[kjSkipLink]", inputs: ["kjSkipLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13721
+ }
13722
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSkipLinkComponent, decorators: [{
13723
+ type: Component,
13724
+ args: [{ selector: 'kj-skip-link', standalone: true, imports: [KjSkipLink], template: `
13725
+ <a kjSkipLink class="kj-skip-link" [kjSkipLink]="kjTarget()">
13726
+ <ng-content>Skip to main content</ng-content>
13727
+ </a>
13728
+ `, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-skip-link{--kj-skip-link-bg: var(--kj-bg-primary);--kj-skip-link-fg: var(--kj-fg-on-primary);--kj-skip-link-radius: var(--kj-radius-field, .25rem);--kj-skip-link-shadow: var(--kj-shadow-lg);--kj-skip-link-offset: var(--kj-space-sm, .5rem);--kj-skip-link-z: 1000;position:fixed;top:0;left:var(--kj-skip-link-offset);z-index:var(--kj-skip-link-z);transform:translateY(-150%);transition:transform var(--kj-transition, .15s ease);display:inline-block;padding:.625rem 1rem;min-height:44px;box-sizing:border-box;background:var(--kj-skip-link-bg);color:var(--kj-skip-link-fg);border-radius:var(--kj-skip-link-radius);box-shadow:var(--kj-skip-link-shadow);font:inherit;font-weight:600;line-height:1.4;text-decoration:none;white-space:nowrap}.kj-skip-link:focus,.kj-skip-link:focus-visible{transform:translateY(var(--kj-skip-link-offset));outline:3px solid var(--kj-fg-primary);outline-offset:2px}@media(prefers-reduced-motion:reduce){.kj-skip-link{transition:none}}}\n"] }]
13729
+ }], propDecorators: { kjTarget: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjTarget", required: false }] }] } });
13730
+
11060
13731
  /**
11061
13732
  * Styled wrapper around the headless `KjSlider` directive family.
11062
13733
  *
@@ -11618,177 +14289,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
11618
14289
  }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-speed-dial{--kj-speed-dial-gap: var(--kj-space-md);--kj-speed-dial-edge: var(--kj-space-2xl);--kj-speed-dial-trigger-size: 3.5rem;--kj-speed-dial-action-size: 2.75rem;--kj-speed-dial-shadow: 0 6px 16px rgb(0 0 0 / .18);--kj-speed-dial-stagger: 30ms;--kj-speed-dial-duration: .18s;position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:var(--kj-speed-dial-gap);z-index:100}.kj-speed-dial[data-direction=up]{flex-direction:column-reverse}.kj-speed-dial[data-direction=down]{flex-direction:column}.kj-speed-dial[data-direction=left]{flex-direction:row-reverse}.kj-speed-dial[data-direction=right]{flex-direction:row}.kj-speed-dial[data-position=bottom-right]{position:fixed;right:var(--kj-speed-dial-edge);bottom:var(--kj-speed-dial-edge)}.kj-speed-dial[data-position=bottom-left]{position:fixed;left:var(--kj-speed-dial-edge);bottom:var(--kj-speed-dial-edge)}.kj-speed-dial[data-position=top-right]{position:fixed;right:var(--kj-speed-dial-edge);top:var(--kj-speed-dial-edge)}.kj-speed-dial[data-position=top-left]{position:fixed;left:var(--kj-speed-dial-edge);top:var(--kj-speed-dial-edge)}.kj-speed-dial-trigger{--kj-button-radius: 9999px;--kj-button-padding-x: 0;--kj-button-padding-y: 0;--kj-button-shadow: var(--kj-speed-dial-shadow);width:var(--kj-speed-dial-trigger-size);height:var(--kj-speed-dial-trigger-size);min-width:var(--kj-speed-dial-trigger-size);flex:0 0 auto}.kj-speed-dial-trigger[data-state=open]>*{transform:rotate(45deg);transition:transform var(--kj-speed-dial-duration) ease}.kj-speed-dial-trigger>*{display:inline-flex;transition:transform var(--kj-speed-dial-duration) ease}.kj-speed-dial-actions{display:inline-flex;gap:var(--kj-speed-dial-gap);align-items:center;justify-content:center;pointer-events:none;opacity:0;transition:opacity var(--kj-speed-dial-duration) ease}.kj-speed-dial-actions[data-direction=up]{flex-direction:column-reverse}.kj-speed-dial-actions[data-direction=down]{flex-direction:column}.kj-speed-dial-actions[data-direction=left]{flex-direction:row-reverse}.kj-speed-dial-actions[data-direction=right]{flex-direction:row}.kj-speed-dial-actions[aria-hidden=true]{visibility:hidden;pointer-events:none}.kj-speed-dial-actions[data-expanded]{opacity:1;visibility:visible;pointer-events:auto}.kj-speed-dial-actions[data-direction=up]>*{transform:translateY(8px)}.kj-speed-dial-actions[data-direction=down]>*{transform:translateY(-8px)}.kj-speed-dial-actions[data-direction=left]>*{transform:translate(8px)}.kj-speed-dial-actions[data-direction=right]>*{transform:translate(-8px)}.kj-speed-dial-actions[data-expanded]>*{transform:translateZ(0);transition:transform var(--kj-speed-dial-duration) ease,opacity var(--kj-speed-dial-duration) ease;transition-delay:calc(var(--kj-speed-dial-stagger) * var(--kj-speed-dial-i, 0))}.kj-speed-dial-actions>*:nth-child(1){--kj-speed-dial-i: 0}.kj-speed-dial-actions>*:nth-child(2){--kj-speed-dial-i: 1}.kj-speed-dial-actions>*:nth-child(3){--kj-speed-dial-i: 2}.kj-speed-dial-actions>*:nth-child(4){--kj-speed-dial-i: 3}.kj-speed-dial-actions>*:nth-child(5){--kj-speed-dial-i: 4}.kj-speed-dial-actions>*:nth-child(6){--kj-speed-dial-i: 5}.kj-speed-dial-action{--kj-button-radius: 9999px;--kj-button-padding-x: 0;--kj-button-padding-y: 0;--kj-button-shadow: var(--kj-speed-dial-shadow);width:var(--kj-speed-dial-action-size);height:var(--kj-speed-dial-action-size);min-width:var(--kj-speed-dial-action-size);flex:0 0 auto}@media(prefers-reduced-motion:reduce){.kj-speed-dial-trigger>*,.kj-speed-dial-actions,.kj-speed-dial-actions>*{transition:none}.kj-speed-dial-actions>*{transform:none}}}\n"] }]
11619
14290
  }], propDecorators: { kjVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjVariant", required: false }] }], kjSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSize", required: false }] }], kjDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjDisabled", required: false }] }], kjCloseOnActivate: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjCloseOnActivate", required: false }] }], kjAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaLabel", required: false }] }] } });
11620
14291
 
11621
- /**
11622
- * Styled wrapper around the headless `KjSpinner` directive.
11623
- *
11624
- * Composes `KjSpinner` via `hostDirectives` so the wrapper's host element is
11625
- * *the* spinner — `role="status"`, `aria-live="polite"`, `aria-atomic="true"`,
11626
- * the `aria-label` default ("Loading"), `data-animation`, and
11627
- * `data-reduced-motion` all land on `<kj-spinner>` itself. `kjVariant` and
11628
- * `kjSize` are wrapper-level inputs that the host mirrors to `data-variant` /
11629
- * `data-size` (the directive's own nested `KjVariant` / `KjSize` host
11630
- * directives are not transitively exposed through outer composition, so the
11631
- * wrapper takes over the data-attribute reflection at this layer).
11632
- *
11633
- * The template renders an `aria-hidden` glyph element (the visual shape that
11634
- * theme CSS keyframes drive per `data-animation`) and, when no
11635
- * `aria-labelledby` was authored on the host, a `kjVisuallyHidden` label so
11636
- * AT always finds an accessible name.
11637
- *
11638
- * **Indeterminate-only.** The spinner answers "something is happening" — it
11639
- * has no value model. For "x of y" use Progress Bar; for missing-content
11640
- * placeholders use Skeleton.
11641
- *
11642
- * @example
11643
- * ```html
11644
- * <kj-spinner />
11645
- * <kj-spinner kjVariant="primary" kjSize="lg" kjAnimation="dots" kjAriaLabel="Sending" />
11646
- * ```
11647
- * @doc-example Default
11648
- * The default playground — `spin` animation, `md` size, neutral variant,
11649
- * default `aria-label="Loading"`.
11650
- * @doc-file spinner.example.ts
11651
- * @doc-example Usage
11652
- * A walkthrough of the most common spinner usages — size, variant,
11653
- * animation glyph, and inline placement next to copy.
11654
- * @doc-file spinner.usage.example.ts
11655
- * @doc-example Sizes
11656
- * `xs` / `sm` / `md` / `lg` presets. There is intentionally no `xl` — that
11657
- * size almost always wants a determinate Progress Bar instead.
11658
- * @doc-file spinner.sizes.example.ts
11659
- * @doc-example Variants
11660
- * `neutral` (inherits `currentColor`), `primary`, `success`, `warning`,
11661
- * `error`, `info`.
11662
- * @doc-file spinner.variants.example.ts
11663
- * @doc-example Animations
11664
- * Animation shape preset — `spin`, `dots`, `bars`, etc. Themes own the
11665
- * keyframes per value.
11666
- * @doc-file spinner.animations.example.ts
11667
- * @doc-example Inside a button
11668
- * Embed the spinner inline next to a label to communicate in-flight work.
11669
- * @doc-file spinner.in-button.example.ts
11670
- *
11671
- * @doc-keyboard
11672
- * — — Non-interactive. The spinner is purely a status indicator.
11673
- *
11674
- * @doc-aria
11675
- * role="status" — set on the host so AT announces it as a live status region
11676
- * aria-live — "polite" so the label is read without interrupting the user
11677
- * aria-atomic — "true" so the full label is announced on change
11678
- * aria-label — Defaults to "Loading"; override per context (e.g. "Sending")
11679
- * data-animation — Mirrors the resolved animation for theme hooks
11680
- * data-variant — Mirrors the resolved variant for theme hooks
11681
- * data-size — Mirrors the resolved size for theme hooks
11682
- *
11683
- * @doc-touch
11684
- * — — Non-interactive; no touch target required.
11685
- *
11686
- * @doc-a11y
11687
- * Indeterminate-only — answers "something is happening", with no value model.
11688
- * Honours `prefers-reduced-motion` via `data-reduced-motion` on the host, so
11689
- * themes can swap a calmer animation. When the consumer authors
11690
- * `aria-labelledby` on the host the wrapper skips the visually-hidden label
11691
- * to avoid double-naming.
11692
- *
11693
- * @doc-related progress-bar,skeleton,toast
11694
- *
11695
- * @doc-css-var
11696
- * --kj-spinner-size — Glyph diameter. Sizes (xs/sm/md/lg) override.
11697
- * --kj-spinner-color — Foreground color of the glyph. Variants set this; neutral inherits currentColor.
11698
- * --kj-spinner-track — Track/background color for the spin arc.
11699
- * --kj-spinner-duration — Base animation duration. Other animations scale off this.
11700
- *
11701
- * @doc-category Library/Feedback
11702
- * @doc
11703
- * @doc-name spinner
11704
- * @doc-description Themed indeterminate loading spinner with variant, size, and animation glyph options.
11705
- * @doc-is-main
11706
- */
11707
- class KjSpinnerComponent {
11708
- /**
11709
- * Color preset reflected to `data-variant` on the host. Defaults to
11710
- * `'neutral'`, which resolves to `currentColor` in shipped themes — so a
11711
- * spinner inside a coloured surface inherits its parent's text colour.
11712
- */
11713
- kjVariant = input('neutral', /* @ts-ignore */
11714
- ...(ngDevMode ? [{ debugName: "kjVariant" }] : /* istanbul ignore next */ []));
11715
- /**
11716
- * Size preset reflected to `data-size` on the host. Defaults to `'md'`.
11717
- * Sizes ship as `xs | sm | md | lg`; an `xl` is intentionally absent — a
11718
- * spinner that big almost always wants a determinate Progress Bar instead.
11719
- */
11720
- kjSize = input('md', /* @ts-ignore */
11721
- ...(ngDevMode ? [{ debugName: "kjSize" }] : /* istanbul ignore next */ []));
11722
- /**
11723
- * Animation shape preset forwarded to `KjSpinner.kjAnimation` via the
11724
- * composed host directive. Reflects on the host as `data-animation`.
11725
- * Themes own the keyframes per value.
11726
- */
11727
- kjAnimation = input('spin', /* @ts-ignore */
11728
- ...(ngDevMode ? [{ debugName: "kjAnimation" }] : /* istanbul ignore next */ []));
11729
- /**
11730
- * Accessible name forwarded to `KjSpinner.kjAriaLabel` via the composed
11731
- * host directive. Default `'Loading'`. Used both as the host's
11732
- * `aria-label` and as the visually-hidden text rendered inside the
11733
- * wrapper when no consumer-authored `aria-labelledby` is on the element.
11734
- */
11735
- kjAriaLabel = input('Loading', /* @ts-ignore */
11736
- ...(ngDevMode ? [{ debugName: "kjAriaLabel" }] : /* istanbul ignore next */ []));
11737
- el = inject(ElementRef);
11738
- /**
11739
- * Snapshotted at construction: did the consumer author `aria-labelledby`
11740
- * directly on `<kj-spinner>`? If so the accessible name is the referenced
11741
- * element and we must not project a hidden duplicate. Read in the
11742
- * constructor — by the time the template renders the directive may have
11743
- * stamped its own attributes on the host.
11744
- */
11745
- hasAuthoredLabelledBy;
11746
- /**
11747
- * `true` when the consumer did **not** author `aria-labelledby` on the
11748
- * wrapper — i.e. the spinner's accessible name is its `aria-label`. The
11749
- * wrapper renders a `kjVisuallyHidden` copy of the label as inner text so
11750
- * AT that prefers content over `aria-label` (or that announces a
11751
- * `role="status"` region's body on insertion) still has a name to read.
11752
- * A consumer-authored `aria-labelledby` opts out of that hidden copy to
11753
- * avoid double-naming the host.
11754
- */
11755
- shouldRenderHiddenLabel = computed(() => !this.hasAuthoredLabelledBy, /* @ts-ignore */
11756
- ...(ngDevMode ? [{ debugName: "shouldRenderHiddenLabel" }] : /* istanbul ignore next */ []));
11757
- constructor() {
11758
- this.hasAuthoredLabelledBy =
11759
- this.el.nativeElement.hasAttribute('aria-labelledby');
11760
- }
11761
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11762
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: KjSpinnerComponent, isStandalone: true, selector: "kj-spinner", inputs: { kjVariant: { classPropertyName: "kjVariant", publicName: "kjVariant", isSignal: true, isRequired: false, transformFunction: null }, kjSize: { classPropertyName: "kjSize", publicName: "kjSize", isSignal: true, isRequired: false, transformFunction: null }, kjAnimation: { classPropertyName: "kjAnimation", publicName: "kjAnimation", isSignal: true, isRequired: false, transformFunction: null }, kjAriaLabel: { classPropertyName: "kjAriaLabel", publicName: "kjAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variant": "kjVariant()", "attr.data-size": "kjSize()" }, classAttribute: "kj-spinner" }, hostDirectives: [{ directive: i1.KjSpinner, inputs: ["kjAnimation", "kjAnimation", "kjAriaLabel", "kjAriaLabel"] }], ngImport: i0, template: `
11763
- <span class="kj-spinner__glyph" aria-hidden="true"></span>
11764
- @if (shouldRenderHiddenLabel()) {
11765
- <span kjVisuallyHidden>{{ kjAriaLabel() }}</span>
11766
- }
11767
- `, isInline: true, styles: ["@layer kj.component{.kj-spinner{--kj-spinner-size: 1.25rem;--kj-spinner-color: currentColor;--kj-spinner-track: color-mix(in srgb, currentColor 20%, transparent);--kj-spinner-duration: .7s;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--kj-spinner-size);block-size:var(--kj-spinner-size);color:var(--kj-spinner-color);pointer-events:none}.kj-spinner[data-size=xs]{--kj-spinner-size: .75rem}.kj-spinner[data-size=sm]{--kj-spinner-size: 1rem}.kj-spinner[data-size=md]{--kj-spinner-size: 1.25rem}.kj-spinner[data-size=lg]{--kj-spinner-size: 1.75rem}.kj-spinner[data-variant=neutral]{--kj-spinner-color: currentColor}.kj-spinner[data-variant=primary]{--kj-spinner-color: var(--kj-fg-primary)}.kj-spinner[data-variant=secondary]{--kj-spinner-color: var(--kj-fg-default)}.kj-spinner[data-variant=success]{--kj-spinner-color: var(--kj-fg-success, #16a34a)}.kj-spinner[data-variant=warning]{--kj-spinner-color: var(--kj-fg-warning, #d97706)}.kj-spinner[data-variant=error]{--kj-spinner-color: var(--kj-fg-danger, #dc2626)}.kj-spinner[data-variant=info]{--kj-spinner-color: var(--kj-fg-info, #2563eb)}.kj-spinner__glyph{display:inline-block;inline-size:100%;block-size:100%}.kj-spinner[data-animation=spin] .kj-spinner__glyph{border:2px solid var(--kj-spinner-track);border-block-start-color:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-spin var(--kj-spinner-duration) linear infinite}.kj-spinner[data-animation=pulse] .kj-spinner__glyph{background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-pulse calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots]{inline-size:auto}.kj-spinner[data-animation=dots] .kj-spinner__glyph{display:inline-flex;gap:calc(var(--kj-spinner-size) * .25);inline-size:auto;block-size:100%}.kj-spinner[data-animation=dots] .kj-spinner__glyph:before,.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .3);block-size:calc(var(--kj-spinner-size) * .3);background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-dots calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots] .kj-spinner__glyph{background:transparent}.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-animation=bars]{inline-size:auto}.kj-spinner[data-animation=bars] .kj-spinner__glyph{display:inline-flex;align-items:stretch;gap:calc(var(--kj-spinner-size) * .15);inline-size:auto;block-size:100%}.kj-spinner[data-animation=bars] .kj-spinner__glyph:before,.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .2);background:var(--kj-spinner-color);border-radius:calc(var(--kj-spinner-size) * .05);animation:kj-spinner-bars calc(var(--kj-spinner-duration) * 1.6) ease-in-out infinite;transform-origin:center}.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:before,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:after{animation:kj-spinner-reduced-motion 1.6s ease-in-out infinite!important}}@keyframes kj-spinner-spin{to{transform:rotate(360deg)}}@keyframes kj-spinner-pulse{0%,to{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}@keyframes kj-spinner-dots{0%,80%,to{transform:scale(.4);opacity:.4}40%{transform:scale(1);opacity:1}}@keyframes kj-spinner-bars{0%,40%,to{transform:scaleY(.4)}20%{transform:scaleY(1)}}@keyframes kj-spinner-reduced-motion{0%,to{opacity:.45}50%{opacity:1}}\n"], dependencies: [{ kind: "directive", type: KjVisuallyHidden, selector: "[kjVisuallyHidden]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
11768
- }
11769
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjSpinnerComponent, decorators: [{
11770
- type: Component,
11771
- args: [{ selector: 'kj-spinner', standalone: true, imports: [KjVisuallyHidden], hostDirectives: [
11772
- {
11773
- directive: KjSpinner,
11774
- // KjSpinner's own surface — kjVariant + kjSize live on its nested
11775
- // KjVariant / KjSize and are not surfaced through this outer
11776
- // composition; they are re-exposed as wrapper inputs below and wired
11777
- // straight to the host's data-variant / data-size attributes.
11778
- inputs: ['kjAnimation', 'kjAriaLabel'],
11779
- },
11780
- ], template: `
11781
- <span class="kj-spinner__glyph" aria-hidden="true"></span>
11782
- @if (shouldRenderHiddenLabel()) {
11783
- <span kjVisuallyHidden>{{ kjAriaLabel() }}</span>
11784
- }
11785
- `, encapsulation: ViewEncapsulation.None, host: {
11786
- 'class': 'kj-spinner',
11787
- '[attr.data-variant]': 'kjVariant()',
11788
- '[attr.data-size]': 'kjSize()',
11789
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-spinner{--kj-spinner-size: 1.25rem;--kj-spinner-color: currentColor;--kj-spinner-track: color-mix(in srgb, currentColor 20%, transparent);--kj-spinner-duration: .7s;display:inline-flex;align-items:center;justify-content:center;inline-size:var(--kj-spinner-size);block-size:var(--kj-spinner-size);color:var(--kj-spinner-color);pointer-events:none}.kj-spinner[data-size=xs]{--kj-spinner-size: .75rem}.kj-spinner[data-size=sm]{--kj-spinner-size: 1rem}.kj-spinner[data-size=md]{--kj-spinner-size: 1.25rem}.kj-spinner[data-size=lg]{--kj-spinner-size: 1.75rem}.kj-spinner[data-variant=neutral]{--kj-spinner-color: currentColor}.kj-spinner[data-variant=primary]{--kj-spinner-color: var(--kj-fg-primary)}.kj-spinner[data-variant=secondary]{--kj-spinner-color: var(--kj-fg-default)}.kj-spinner[data-variant=success]{--kj-spinner-color: var(--kj-fg-success, #16a34a)}.kj-spinner[data-variant=warning]{--kj-spinner-color: var(--kj-fg-warning, #d97706)}.kj-spinner[data-variant=error]{--kj-spinner-color: var(--kj-fg-danger, #dc2626)}.kj-spinner[data-variant=info]{--kj-spinner-color: var(--kj-fg-info, #2563eb)}.kj-spinner__glyph{display:inline-block;inline-size:100%;block-size:100%}.kj-spinner[data-animation=spin] .kj-spinner__glyph{border:2px solid var(--kj-spinner-track);border-block-start-color:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-spin var(--kj-spinner-duration) linear infinite}.kj-spinner[data-animation=pulse] .kj-spinner__glyph{background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-pulse calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots]{inline-size:auto}.kj-spinner[data-animation=dots] .kj-spinner__glyph{display:inline-flex;gap:calc(var(--kj-spinner-size) * .25);inline-size:auto;block-size:100%}.kj-spinner[data-animation=dots] .kj-spinner__glyph:before,.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .3);block-size:calc(var(--kj-spinner-size) * .3);background:var(--kj-spinner-color);border-radius:50%;animation:kj-spinner-dots calc(var(--kj-spinner-duration) * 2) ease-in-out infinite}.kj-spinner[data-animation=dots] .kj-spinner__glyph{background:transparent}.kj-spinner[data-animation=dots] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-animation=bars]{inline-size:auto}.kj-spinner[data-animation=bars] .kj-spinner__glyph{display:inline-flex;align-items:stretch;gap:calc(var(--kj-spinner-size) * .15);inline-size:auto;block-size:100%}.kj-spinner[data-animation=bars] .kj-spinner__glyph:before,.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{content:\"\";inline-size:calc(var(--kj-spinner-size) * .2);background:var(--kj-spinner-color);border-radius:calc(var(--kj-spinner-size) * .05);animation:kj-spinner-bars calc(var(--kj-spinner-duration) * 1.6) ease-in-out infinite;transform-origin:center}.kj-spinner[data-animation=bars] .kj-spinner__glyph:after{animation-delay:calc(var(--kj-spinner-duration) * .4)}.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:before,.kj-spinner[data-reduced-motion=true] .kj-spinner__glyph:after{animation:kj-spinner-reduced-motion 1.6s ease-in-out infinite!important}}@keyframes kj-spinner-spin{to{transform:rotate(360deg)}}@keyframes kj-spinner-pulse{0%,to{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}@keyframes kj-spinner-dots{0%,80%,to{transform:scale(.4);opacity:.4}40%{transform:scale(1);opacity:1}}@keyframes kj-spinner-bars{0%,40%,to{transform:scaleY(.4)}20%{transform:scaleY(1)}}@keyframes kj-spinner-reduced-motion{0%,to{opacity:.45}50%{opacity:1}}\n"] }]
11790
- }], ctorParameters: () => [], propDecorators: { kjVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjVariant", required: false }] }], kjSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjSize", required: false }] }], kjAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAnimation", required: false }] }], kjAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaLabel", required: false }] }] } });
11791
-
11792
14292
  /**
11793
14293
  * Styled root wrapper around the headless `KjStepper` directive.
11794
14294
  *
@@ -12083,10 +14583,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
12083
14583
  * </div>
12084
14584
  * ```
12085
14585
  *
12086
- * @doc-category Components/Data
12087
- * @doc
12088
- * @doc-name table-virtual
12089
- * @doc-description Row virtualization adapter on @tanstack/virtual-core. Exposes virtualRows / paddingTop / paddingBottom / totalSize signals for the styled data table.
14586
+ * Documented as part of the data table on the `table` page — not a standalone
14587
+ * docs entry.
12090
14588
  */
12091
14589
  class KjTableVirtual {
12092
14590
  /** Total number of rows in the underlying dataset. */
@@ -14965,10 +17463,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
14965
17463
  * The toolbar must sit inside a `<kj-table>` (or any element hosting
14966
17464
  * the `KJ_TABLE` token) so it can resolve the table instance via DI.
14967
17465
  *
14968
- * @doc-category Components/Data
14969
- * @doc
14970
- * @doc-name table-toolbar
14971
- * @doc-description Toolbar chrome above the data table — quick filter, density, column visibility, export, and bulk-action slot.
17466
+ * Documented as part of the data table on the `table` page — not a standalone
17467
+ * docs entry.
14972
17468
  */
14973
17469
  class KjTableToolbarComponent {
14974
17470
  /** The host table — resolved through `KJ_TABLE` injected from any ancestor. */
@@ -15207,10 +17703,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
15207
17703
  * </kj-table>
15208
17704
  * ```
15209
17705
  *
15210
- * @doc-category Components/Data
15211
- * @doc
15212
- * @doc-name table-pagination
15213
- * @doc-description Page-size selector, First/Prev/Next/Last nav, and "Showing N–M of total" summary bound to the parent table.
17706
+ * Documented as part of the data table on the `table` page — not a standalone
17707
+ * docs entry.
15214
17708
  */
15215
17709
  class KjTablePaginationComponent {
15216
17710
  /** Available page sizes for the selector. */
@@ -15533,10 +18027,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
15533
18027
  * </kj-table>
15534
18028
  * ```
15535
18029
  *
15536
- * @doc-category Components/Data
15537
- * @doc
15538
- * @doc-name table-side-panel
15539
- * @doc-description Service-launched drawer listing every column with visibility, pin, and group controls.
18030
+ * Documented as part of the data table on the `table` page — not a standalone
18031
+ * docs entry.
15540
18032
  */
15541
18033
  class KjTableSidePanelComponent {
15542
18034
  /** Whether the side panel is visible. Two-way bindable. */
@@ -15616,10 +18108,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
15616
18108
  * </table>
15617
18109
  * ```
15618
18110
  *
15619
- * @doc-category Components/Data
15620
- * @doc
15621
- * @doc-name table-status-bar
15622
- * @doc-description Counts strip showing row count, selected count, and filtered indicator.
18111
+ * Documented as part of the data table on the `table` page — not a standalone
18112
+ * docs entry.
15623
18113
  */
15624
18114
  class KjTableStatusBarComponent {
15625
18115
  table = inject(KJ_TABLE);
@@ -16741,11 +19231,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
16741
19231
  */
16742
19232
  class KjToastWrapperComponent {
16743
19233
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjToastWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16744
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjToastWrapperComponent, isStandalone: true, selector: "kj-toast-wrapper", host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-left:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19234
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjToastWrapperComponent, isStandalone: true, selector: "kj-toast-wrapper", host: { styleAttribute: "display: contents;" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-inline-start:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16745
19235
  }
16746
19236
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjToastWrapperComponent, decorators: [{
16747
19237
  type: Component,
16748
- args: [{ selector: 'kj-toast-wrapper', standalone: true, template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-left:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"] }]
19238
+ args: [{ selector: 'kj-toast-wrapper', standalone: true, template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-inline-start:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"] }]
16749
19239
  }] });
16750
19240
  /**
16751
19241
  * Toast viewport. Mount once near your trigger button (or in your app shell).
@@ -16767,7 +19257,7 @@ class KjToastViewportComponent {
16767
19257
  </li>
16768
19258
  }
16769
19259
  </ol>
16770
- `, isInline: true, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-left:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"], dependencies: [{ kind: "directive", type: KjToastViewport, selector: "[kjToastViewport]", inputs: ["kjToastDefaultTemplate", "kjToastMaxVisible", "kjToastGap", "kjToastBaseZIndex", "kjToastPositionX", "kjToastPositionY", "kjToastExpand", "kjToastPauseOnHover"], exportAs: ["kjToastViewport"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19260
+ `, isInline: true, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-inline-start:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"], dependencies: [{ kind: "directive", type: KjToastViewport, selector: "[kjToastViewport]", inputs: ["kjToastDefaultTemplate", "kjToastMaxVisible", "kjToastGap", "kjToastBaseZIndex", "kjToastPositionX", "kjToastPositionY", "kjToastExpand", "kjToastPauseOnHover"], exportAs: ["kjToastViewport"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16771
19261
  }
16772
19262
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjToastViewportComponent, decorators: [{
16773
19263
  type: Component,
@@ -16784,7 +19274,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
16784
19274
  </li>
16785
19275
  }
16786
19276
  </ol>
16787
- `, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-left:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"] }]
19277
+ `, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["@layer kj.component{.kj-toast-viewport{position:fixed;list-style:none;padding:0;margin:0;z-index:var(--kj-toast-z-index, 1000);bottom:1rem;right:1rem;width:22rem;max-width:calc(100vw - 2rem)}.kj-toast-viewport[data-position-y=bottom]{bottom:1rem;top:auto}.kj-toast-viewport[data-position-y=top]{top:1rem;bottom:auto}.kj-toast-viewport[data-position-x=end]{right:1rem;left:auto}.kj-toast-viewport[data-position-x=start]{left:1rem;right:auto}.kj-toast-viewport[data-position-x=center]{left:50%;right:auto;transform:translate(-50%)}.kj-toast-viewport li{position:absolute;left:0;right:0;transition:transform .4s cubic-bezier(.21,.61,.35,1),opacity .3s ease}.kj-toast-viewport[data-position-y=bottom] li{bottom:0}.kj-toast-viewport[data-position-y=top] li{top:0}.kj-toast-viewport[data-expanded=false] .kj-toast:not([data-front=true]){height:var(--kj-toast-front-height);overflow:hidden;transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px) * -1)) scale(calc(1 - (var(--kj-toast-index) - 1) * .06));opacity:calc(1 - (var(--kj-toast-index) - 1) * .25)}.kj-toast-viewport[data-position-y=top][data-expanded=false] .kj-toast:not([data-front=true]){transform:translateY(calc((var(--kj-toast-index) - 1) * var(--kj-toast-gap, 14px))) scale(calc(1 - (var(--kj-toast-index) - 1) * .06))}.kj-toast-viewport[data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px)) * -1))}.kj-toast-viewport[data-position-y=top][data-expanded=true] .kj-toast{transform:translateY(calc((var(--kj-toast-index) - 1) * (var(--kj-toast-height, 0px) + var(--kj-toast-gap, 14px))))}.kj-toast{display:flex;align-items:center;gap:var(--kj-space-md, .75rem);padding:var(--kj-space-md, .75rem) var(--kj-space-lg, 1rem);min-width:18rem;font:.875rem / 1.4 var(--kj-font-sans, sans-serif);border-radius:var(--kj-radius-box, .5rem);box-shadow:0 4px 16px #0000002e,0 1px #ffffff0a inset;border:var(--kj-border, 1px) solid var(--kj-border-default, #e2e8f0);background:var(--kj-bg-elevated, #fff);color:var(--kj-fg-default, #1a202c);animation:kj-toast-enter .35s cubic-bezier(.21,.61,.35,1)}@keyframes kj-toast-enter{0%{opacity:0;transform:translateY(100%) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}.kj-toast[data-variant=success]{background:var(--kj-bg-success, #16a34a);color:var(--kj-fg-on-success, #fff);border-color:transparent}.kj-toast[data-variant=warning]{background:var(--kj-bg-warning, #d97706);color:var(--kj-fg-on-warning, #fff);border-color:transparent}.kj-toast[data-variant=destructive]{background:var(--kj-bg-danger, #dc2626);color:var(--kj-fg-on-danger, #fff);border-color:transparent}.kj-toast-close{background:transparent;border:0;color:inherit;cursor:pointer;padding:4px 6px;border-radius:4px;line-height:1;font-size:1.1rem;opacity:.7;margin-inline-start:auto;flex-shrink:0}.kj-toast-close:hover{opacity:1;background:#00000014}.kj-toast-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}}\n"] }]
16788
19278
  }] });
16789
19279
  /**
16790
19280
  * Single toast item. Bind `[variant]` from `ctx.variant` and `[id]` from `ctx.id`.
@@ -16850,7 +19340,7 @@ class KjToastCloseComponent {
16850
19340
  [kjToastClose]="toastId()"
16851
19341
  [attr.aria-label]="ariaLabel()"
16852
19342
  class="kj-toast-close"
16853
- ><ng-content /></button>`, isInline: true, dependencies: [{ kind: "directive", type: KjToastClose, selector: "[kjToastClose]", inputs: ["kjToastClose"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19343
+ ><ng-content /></button>`, isInline: true, dependencies: [{ kind: "directive", type: KjToastClose, selector: "[kjToastClose]", inputs: ["kjToastClose", "kjToastCloseLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16854
19344
  }
16855
19345
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjToastCloseComponent, decorators: [{
16856
19346
  type: Component,
@@ -17176,10 +19666,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17176
19666
  * --kj-command-item-align — Cross-axis alignment of row contents. Defaults to `center`.
17177
19667
  * --kj-command-item-gap — Gap between icon and label inside a row. Defaults to --kj-space-md.
17178
19668
  *
19669
+ * @doc-category Library/Actions
17179
19670
  * @doc
17180
19671
  * @doc-name command-palette
17181
19672
  * @doc-description Themed Cmd-K modal command palette with fuzzy filtering, grouped results, and keyboard navigation.
17182
- * @doc-is-main
17183
19673
  */
17184
19674
  class KjCommandPaletteFooter {
17185
19675
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandPaletteFooter, deps: [], target: i0.ɵɵFactoryTarget.Directive });
@@ -17281,6 +19771,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17281
19771
  * @doc-category Library/Actions
17282
19772
  * @doc
17283
19773
  * @doc-name command-palette
19774
+ * @doc-is-main
17284
19775
  */
17285
19776
  class KjCommandPaletteComponent {
17286
19777
  /** Input placeholder text. */
@@ -17312,7 +19803,22 @@ class KjCommandPaletteComponent {
17312
19803
  ...(ngDevMode ? [{ debugName: "customFooter" }] : /* istanbul ignore next */ []));
17313
19804
  destroyRef = inject(DestroyRef);
17314
19805
  platformId = inject(PLATFORM_ID);
19806
+ /** The composed headless palette (host directive) — owns query + active state. */
19807
+ palette = inject(KjCommandPalette);
17315
19808
  constructor() {
19809
+ // Reset the search query + active item when the palette closes, so the
19810
+ // next open starts fresh instead of restoring the previous search. Paired
19811
+ // with KjCommandInput reflecting the query signal back to the DOM input,
19812
+ // this also clears the visible text.
19813
+ let wasOpen = false;
19814
+ effect(() => {
19815
+ const open = this.kjOpen();
19816
+ if (wasOpen && !open) {
19817
+ this.palette.kjQuery.set('');
19818
+ this.palette.kjValue.set(null);
19819
+ }
19820
+ wasOpen = open;
19821
+ });
17316
19822
  afterNextRender(() => {
17317
19823
  if (!isPlatformBrowser(this.platformId))
17318
19824
  return;
@@ -17416,7 +19922,7 @@ class KjCommandPaletteComponent {
17416
19922
  }
17417
19923
  </div>
17418
19924
  </div>
17419
- `, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: KjCommandInput, selector: "input[kjCommandInput]", exportAs: ["kjCommandInput"] }, { kind: "directive", type: KjCommandList, selector: "[kjCommandList]" }, { kind: "directive", type: KjCommandEmpty, selector: "[kjCommandEmpty]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
19925
+ `, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: KjCommandInput, selector: "input[kjCommandInput]", exportAs: ["kjCommandInput"] }, { kind: "directive", type: KjCommandList, selector: "[kjCommandList]" }, { kind: "directive", type: KjCommandEmpty, selector: "[kjCommandEmpty]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
17420
19926
  }
17421
19927
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandPaletteComponent, decorators: [{
17422
19928
  type: Component,
@@ -17475,7 +19981,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17475
19981
  class: 'kj-command-palette',
17476
19982
  style: 'display: contents;',
17477
19983
  '(kjActivate)': 'onActivate()',
17478
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
19984
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
17479
19985
  }], ctorParameters: () => [], propDecorators: { kjPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjPlaceholder", required: false }] }], kjEscBadge: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjEscBadge", required: false }] }], kjAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAriaLabel", required: false }] }], kjOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjOpen", required: false }] }, { type: i0.Output, args: ["kjOpenChange"] }], kjHotkey: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjHotkey", required: false }] }], kjItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjItems", required: false }] }], kjAutoCloseOnActivate: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjAutoCloseOnActivate", required: false }] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KjCommandPaletteItemTemplate), { isSignal: true }] }], customFooter: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KjCommandPaletteFooter), { isSignal: true }] }] } });
17480
19986
  /**
17481
19987
  * Styled command item. Renders a `<button>` with `[kjCommandItem]` applied.
@@ -17502,7 +20008,7 @@ class KjCommandItemComponent {
17502
20008
  isActive = computed(() => this._palette.activeId() !== null && this._palette.activeId() === this._item.id, /* @ts-ignore */
17503
20009
  ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
17504
20010
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17505
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: KjCommandItemComponent, isStandalone: true, selector: "kj-command-item", inputs: { kjValue: { classPropertyName: "kjValue", publicName: "kjValue", isSignal: true, isRequired: false, transformFunction: null }, kjKeywords: { classPropertyName: "kjKeywords", publicName: "kjKeywords", isSignal: true, isRequired: false, transformFunction: null }, kjShortcut: { classPropertyName: "kjShortcut", publicName: "kjShortcut", isSignal: true, isRequired: false, transformFunction: null }, kjDisabled: { classPropertyName: "kjDisabled", publicName: "kjDisabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, properties: { "attr.aria-selected": "isActive() ? \"true\" : \"false\"", "attr.data-active": "isActive() ? \"\" : null" }, classAttribute: "kj-command-item" }, hostDirectives: [{ directive: i1.KjListItem, inputs: ["kjItemValue", "kjValue", "kjItemKeywords", "kjKeywords", "kjShortcut", "kjShortcut", "kjDisabled", "kjDisabled"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20011
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: KjCommandItemComponent, isStandalone: true, selector: "kj-command-item", inputs: { kjValue: { classPropertyName: "kjValue", publicName: "kjValue", isSignal: true, isRequired: false, transformFunction: null }, kjKeywords: { classPropertyName: "kjKeywords", publicName: "kjKeywords", isSignal: true, isRequired: false, transformFunction: null }, kjShortcut: { classPropertyName: "kjShortcut", publicName: "kjShortcut", isSignal: true, isRequired: false, transformFunction: null }, kjDisabled: { classPropertyName: "kjDisabled", publicName: "kjDisabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, properties: { "attr.aria-selected": "isActive() ? \"true\" : \"false\"", "attr.data-active": "isActive() ? \"\" : null" }, classAttribute: "kj-command-item" }, hostDirectives: [{ directive: i1.KjListItem, inputs: ["kjItemValue", "kjValue", "kjItemKeywords", "kjKeywords", "kjShortcut", "kjShortcut", "kjDisabled", "kjDisabled"] }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
17506
20012
  }
17507
20013
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandItemComponent, decorators: [{
17508
20014
  type: Component,
@@ -17519,7 +20025,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17519
20025
  'role': 'option',
17520
20026
  '[attr.aria-selected]': 'isActive() ? "true" : "false"',
17521
20027
  '[attr.data-active]': 'isActive() ? "" : null',
17522
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
20028
+ }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
17523
20029
  }], propDecorators: { kjValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjValue", required: false }] }], kjKeywords: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjKeywords", required: false }] }], kjShortcut: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjShortcut", required: false }] }], kjDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjDisabled", required: false }] }] } });
17524
20030
  /**
17525
20031
  * Styled command group. Auto-hides when all child items are filtered out.
@@ -17538,7 +20044,7 @@ class KjCommandGroupComponent {
17538
20044
  <div class="kj-command-group__label">{{ kjLabel() }}</div>
17539
20045
  }
17540
20046
  <ng-content />
17541
- `, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20047
+ `, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
17542
20048
  }
17543
20049
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandGroupComponent, decorators: [{
17544
20050
  type: Component,
@@ -17547,7 +20053,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17547
20053
  <div class="kj-command-group__label">{{ kjLabel() }}</div>
17548
20054
  }
17549
20055
  <ng-content />
17550
- `, encapsulation: ViewEncapsulation.None, host: { class: 'kj-command-group' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
20056
+ `, encapsulation: ViewEncapsulation.None, host: { class: 'kj-command-group' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
17551
20057
  }], propDecorators: { kjLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjLabel", required: false }] }] } });
17552
20058
  /**
17553
20059
  * Styled command input wrapper. Renders an `<input type="search">` with
@@ -17570,7 +20076,7 @@ class KjCommandInputComponent {
17570
20076
  class="kj-command-input"
17571
20077
  [placeholder]="kjPlaceholder()"
17572
20078
  />
17573
- `, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], dependencies: [{ kind: "directive", type: KjCommandInput, selector: "input[kjCommandInput]", exportAs: ["kjCommandInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20079
+ `, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], dependencies: [{ kind: "directive", type: KjCommandInput, selector: "input[kjCommandInput]", exportAs: ["kjCommandInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
17574
20080
  }
17575
20081
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandInputComponent, decorators: [{
17576
20082
  type: Component,
@@ -17581,7 +20087,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17581
20087
  class="kj-command-input"
17582
20088
  [placeholder]="kjPlaceholder()"
17583
20089
  />
17584
- `, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
20090
+ `, encapsulation: ViewEncapsulation.None, host: { style: 'display: contents;' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
17585
20091
  }], propDecorators: { kjPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjPlaceholder", required: false }] }] } });
17586
20092
  /**
17587
20093
  * Styled separator between command groups.
@@ -17592,11 +20098,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17592
20098
  */
17593
20099
  class KjCommandSeparatorComponent {
17594
20100
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17595
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjCommandSeparatorComponent, isStandalone: true, selector: "kj-command-separator", host: { classAttribute: "kj-command-separator" }, hostDirectives: [{ directive: i1.KjCommandSeparator }], ngImport: i0, template: ``, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20101
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjCommandSeparatorComponent, isStandalone: true, selector: "kj-command-separator", host: { classAttribute: "kj-command-separator" }, hostDirectives: [{ directive: i1.KjCommandSeparator }], ngImport: i0, template: ``, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
17596
20102
  }
17597
20103
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandSeparatorComponent, decorators: [{
17598
20104
  type: Component,
17599
- args: [{ selector: 'kj-command-separator', standalone: true, hostDirectives: [KjCommandSeparator], template: ``, encapsulation: ViewEncapsulation.None, host: { class: 'kj-command-separator' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
20105
+ args: [{ selector: 'kj-command-separator', standalone: true, hostDirectives: [KjCommandSeparator], template: ``, encapsulation: ViewEncapsulation.None, host: { class: 'kj-command-separator' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
17600
20106
  }] });
17601
20107
  /**
17602
20108
  * Styled empty state slot. Shown when no items match the current query.
@@ -17607,11 +20113,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
17607
20113
  */
17608
20114
  class KjCommandEmptyComponent {
17609
20115
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandEmptyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
17610
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjCommandEmptyComponent, isStandalone: true, selector: "kj-command-empty", host: { classAttribute: "kj-command-empty" }, hostDirectives: [{ directive: i1.KjCommandEmpty }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
20116
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.5", type: KjCommandEmptyComponent, isStandalone: true, selector: "kj-command-empty", host: { classAttribute: "kj-command-empty" }, hostDirectives: [{ directive: i1.KjCommandEmpty }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
17611
20117
  }
17612
20118
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjCommandEmptyComponent, decorators: [{
17613
20119
  type: Component,
17614
- args: [{ selector: 'kj-command-empty', standalone: true, hostDirectives: [KjCommandEmpty], template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { class: 'kj-command-empty' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-left:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-left-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
20120
+ args: [{ selector: 'kj-command-empty', standalone: true, hostDirectives: [KjCommandEmpty], template: `<ng-content />`, encapsulation: ViewEncapsulation.None, host: { class: 'kj-command-empty' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".kj-command-palette__shell{display:none}.kj-command-palette__shell.is-open{display:contents}.kj-command-palette__backdrop{position:fixed;inset:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;animation:kj-command-palette-fade .1s ease-out}.kj-command-palette__dialog{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,92vw);display:flex;flex-direction:column;background:var(--kj-bg-elevated);border:1px solid var(--kj-border-default);z-index:1001;overflow:hidden;animation:kj-command-palette-slide .15s ease-out}@keyframes kj-command-palette-fade{0%{opacity:0}to{opacity:1}}@keyframes kj-command-palette-slide{0%{opacity:0;transform:translate(-50%) translateY(-8px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.kj-command-palette__backdrop,.kj-command-palette__dialog{animation:none}}.kj-command-palette__input-wrapper{display:flex;align-items:center;padding:.875rem var(--kj-space-lg, 1.25rem);border-bottom:1px solid var(--kj-border-default);gap:var(--kj-space-md, .75rem)}.kj-command-palette__search-icon{flex-shrink:0;width:1rem;height:1rem;color:var(--kj-fg-muted)}.kj-command-palette__input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none}.kj-command-palette__input::placeholder{color:var(--kj-fg-muted)}.kj-command-palette__input::-webkit-search-cancel-button{display:none}.kj-command-input{flex:1;border:none;outline:none;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);appearance:none;-webkit-appearance:none;width:100%;padding:.875rem var(--kj-space-lg, 1.25rem)}.kj-command-palette__esc-kbd{font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted);background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);padding:.15rem .4rem;flex-shrink:0;cursor:pointer}.kj-command-palette__esc-kbd:hover{color:var(--kj-fg-default)}.kj-command-palette__list{overflow-y:auto;max-height:22rem;padding:var(--kj-space-sm, .375rem) 0}.kj-command-palette__empty,.kj-command-empty{padding:var(--kj-space-xl, 1.5rem) var(--kj-space-lg, 1.25rem);text-align:center;font-family:var(--kj-font-mono);font-size:.8rem;color:var(--kj-fg-muted)}.kj-command-item{display:flex;flex-direction:var(--kj-command-item-direction, row);align-items:var(--kj-command-item-align, center);gap:var(--kj-command-item-gap, var(--kj-space-md, .75rem));width:100%;min-height:2.75rem;padding:.625rem var(--kj-space-lg, 1.25rem);border:none;border-inline-start:2px solid transparent;background:transparent;font-family:var(--kj-font-mono);font-size:.875rem;color:var(--kj-fg-default);text-align:start;cursor:pointer;transition:background .1s}.kj-command-item:hover,.kj-command-item[data-active]{background:var(--kj-bg-surface);border-inline-start-color:var(--kj-bg-primary)}.kj-command-item[aria-disabled=true]{opacity:.45;cursor:not-allowed;pointer-events:none}.kj-command-group{padding-block:.25rem}.kj-command-group__label{padding:.375rem var(--kj-space-lg, 1.25rem) .125rem;font-family:var(--kj-font-mono);font-size:.6rem;font-weight:600;color:var(--kj-fg-muted);letter-spacing:.1em;text-transform:uppercase}.kj-command-separator{height:1px;background:var(--kj-border-default);margin-block:.25rem}.kj-command-palette__footer{display:flex;gap:var(--kj-space-xl, 1.5rem);padding:var(--kj-space-sm, .375rem) var(--kj-space-lg, 1.25rem);border-top:1px solid var(--kj-border-default);background:var(--kj-bg-surface)}.kj-command-palette__footer span{display:flex;align-items:center;gap:.4rem;font-family:var(--kj-font-mono);font-size:.65rem;color:var(--kj-fg-muted)}.kj-command-palette__footer kbd{background:var(--kj-bg-surface);border:1px solid var(--kj-border-default);color:var(--kj-fg-muted);font-family:var(--kj-font-mono);font-size:.6rem;padding:.1rem .35rem}@media(prefers-reduced-motion:reduce){.kj-command-item{transition:none}}\n"] }]
17615
20121
  }] });
17616
20122
 
17617
20123
  /** Walk the tree into a flat array. All nodes are included; visibility is
@@ -18000,5 +20506,5 @@ const KJ_COMPONENTS_VERSION = '0.0.1';
18000
20506
  * Generated bundle index. Do not edit.
18001
20507
  */
18002
20508
 
18003
- export { KJ_COMPONENTS_VERSION, KJ_EDITOR_CONTRACT, KJ_FILTER_CONTEXT, KjAccordionComponent, KjAccordionContentComponent, KjAccordionItemComponent, KjAccordionTriggerComponent, KjAlertActionsComponent, KjAlertComponent, KjAlertDescriptionComponent, KjAlertDismissComponent, KjAlertIconComponent, KjAlertTitleComponent, KjAvatarComponent, KjAvatarGroupComponent, KjBadgeComponent, KjBooleanEditor, KjBreadcrumbComponent, KjBreadcrumbCurrentComponent, KjBreadcrumbEllipsisComponent, KjBreadcrumbItemComponent, KjBreadcrumbLinkComponent, KjBreadcrumbListComponent, KjBreadcrumbSeparatorComponent, KjBulkAction, KjButtonComponent, KjButtonGroupComponent, KjCalendarComponent, KjCardComponent, KjCardContentComponent, KjCardCoverComponent, KjCardFooterComponent, KjCardHeaderComponent, KjCardSubtitleComponent, KjCardTitleComponent, KjCarouselAutoplayComponent, KjCarouselComponent, KjCarouselIndicatorsComponent, KjCarouselNextComponent, KjCarouselPauseComponent, KjCarouselPreviousComponent, KjCarouselSlideComponent, KjCarouselViewportComponent, KjCascadeOptionComponent, KjCascadeSelectComponent, KjCascadeSubPanelComponent, KjCellEditorOutlet, KjCellTemplateDirective, KjChatAvatarComponent, KjChatBubbleComponent, KjChatComponent, KjChatFooterComponent, KjChatHeaderComponent, KjChatLogComponent, KjCheckboxComponent, KjColorPickerComponent, KjComboboxComponent, KjComboboxEmptyComponent, KjComboboxLoadingComponent, KjComboboxOptionComponent, KjCommandEmptyComponent, KjCommandGroupComponent, KjCommandInputComponent, KjCommandItemComponent, KjCommandPaletteComponent, KjCommandPaletteFooter, KjCommandPaletteItemTemplate, KjCommandSeparatorComponent, KjConfirmPopupActionComponent, KjConfirmPopupActionsComponent, KjConfirmPopupCancelComponent, KjConfirmPopupComponent, KjConfirmPopupContentComponent, KjConfirmPopupMessageComponent, KjConfirmPopupTriggerComponent, KjDateEditor, KjDateFilter, KjDatePickerComponent, KjDatetimePickerComponent, KjDialogComponent, KjDividerComponent, KjDrawerComponent, KjDropdownMenuComponent, KjEmptyStateActionsComponent, KjEmptyStateComponent, KjEmptyStateDescriptionComponent, KjEmptyStateIconComponent, KjEmptyStateTitleComponent, KjFieldComponent, KjFieldErrorComponent, KjFieldGroupComponent, KjFieldHelpComponent, KjFieldLabelComponent, KjFileUploadComponent, KjFilterCellOutlet, KjFormActionsComponent, KjFormComponent, KjFormSummaryComponent, KjIconGalleryExample, KjIconUsageExample, KjInputComponent, KjInputGroupAddonComponent, KjInputGroupComponent, KjInputMaskComponent, KjInputMaskCreditCardExample, KjInputMaskCustomTokensExample, KjInputMaskDateExample, KjInputMaskExample, KjInputMaskUsageExample, KjInputMaskValidationExample, KjInputOtpComponent, KjKbdComponent, KjLinkComponent, KjListComponent, KjListItemComponent, KjMenubarComponent, KjMenubarItemComponent, KjNumberEditor, KjNumberFilter, KjNumberInputComponent, KjOptionComponent, KjOverlayBadgeComponent, KjOverlayBadgeContentComponent, KjPaginationComponent, KjPaginationDefaultComponent, KjPaginationEllipsisComponent, KjPaginationFirstComponent, KjPaginationInfoComponent, KjPaginationItemComponent, KjPaginationLastComponent, KjPaginationNextComponent, KjPaginationPreviousComponent, KjPasswordInputComponent, KjPopoverComponent, KjProgressBarComponent, KjRadioComponent, KjRadioGroupComponent, KjSelectComponent, KjSelectEditor, KjSelectFilter, KjSkeletonComponent, KjSliderComponent, KjSpeedDialActionComponent, KjSpeedDialActionsComponent, KjSpeedDialComponent, KjSpeedDialTriggerComponent, KjSpinnerComponent, KjStepComponent, KjStepContentComponent, KjStepLabelComponent, KjStepperComponent, KjStepperNextComponent, KjStepperPreviousComponent, KjStepperResetComponent, KjTabComponent, KjTabListComponent, KjTabPanelComponent, KjTableComponent, KjTablePaginationComponent, KjTableSidePanelComponent, KjTableSidePanelContent, KjTableStatusBarComponent, KjTableToolbarComponent, KjTableVirtual, KjTabsComponent, KjTagComponent, KjTagListComponent, KjTagRemoveComponent, KjTextEditor, KjTextFilter, KjTextareaComponent, KjTimePickerComponent, KjToastCloseComponent, KjToastComponent, KjToastViewportComponent, KjToastWrapperComponent, KjToggleComponent, KjTooltipComponent, KjTreeSelectComponent, KjTreeSelectNodeComponent, LUCIDE_ICON_NAMES, copyToClipboard, downloadString, exportCsv, exportJson, provideLucideIcons, toTsv };
20509
+ export { KJ_COMPONENTS_VERSION, KJ_EDITOR_CONTRACT, KJ_FILTER_CONTEXT, KjAccordionComponent, KjAccordionContentComponent, KjAccordionItemComponent, KjAccordionTriggerComponent, KjActionSheet, KjActionSheetComponent, KjActionSheetRef, KjActionSheetService, KjAlertActionsComponent, KjAlertComponent, KjAlertDescriptionComponent, KjAlertDismissComponent, KjAlertIconComponent, KjAlertTitleComponent, KjAvatarComponent, KjAvatarGroupComponent, KjBadgeComponent, KjBooleanEditor, KjBreadcrumbComponent, KjBreadcrumbCurrentComponent, KjBreadcrumbEllipsisComponent, KjBreadcrumbItemComponent, KjBreadcrumbLinkComponent, KjBreadcrumbListComponent, KjBreadcrumbSeparatorComponent, KjBulkAction, KjButtonComponent, KjButtonGroupComponent, KjCalendarComponent, KjCardComponent, KjCardContentComponent, KjCardCoverComponent, KjCardFooterComponent, KjCardHeaderComponent, KjCardSubtitleComponent, KjCardTitleComponent, KjCarouselAutoplayComponent, KjCarouselComponent, KjCarouselIndicatorsComponent, KjCarouselNextComponent, KjCarouselPauseComponent, KjCarouselPreviousComponent, KjCarouselSlideComponent, KjCarouselViewportComponent, KjCascadeOptionComponent, KjCascadeSelectComponent, KjCascadeSubPanelComponent, KjCellEditorOutlet, KjCellTemplateDirective, KjChartComponent, KjChatAvatarComponent, KjChatBubbleComponent, KjChatComponent, KjChatFooterComponent, KjChatHeaderComponent, KjChatLogComponent, KjChatMessage, KjChatThread, KjCheckboxComponent, KjColorPickerComponent, KjComboboxComponent, KjComboboxEmptyComponent, KjComboboxLoadingComponent, KjComboboxOptionComponent, KjCommandEmptyComponent, KjCommandGroupComponent, KjCommandInputComponent, KjCommandItemComponent, KjCommandPaletteComponent, KjCommandPaletteFooter, KjCommandPaletteItemTemplate, KjCommandSeparatorComponent, KjConfirmPopupActionComponent, KjConfirmPopupActionsComponent, KjConfirmPopupCancelComponent, KjConfirmPopupComponent, KjConfirmPopupContentComponent, KjConfirmPopupMessageComponent, KjConfirmPopupTriggerComponent, KjDateEditor, KjDateFilter, KjDatePickerComponent, KjDateRangePresetsComponent, KjDatetimePickerComponent, KjDialogComponent, KjDirectionToggle, KjDividerComponent, KjDrawerComponent, KjDropdownMenuComponent, KjEditorComponent, KjEmptyStateActionsComponent, KjEmptyStateComponent, KjEmptyStateDescriptionComponent, KjEmptyStateIconComponent, KjEmptyStateTitleComponent, KjFieldComponent, KjFieldErrorComponent, KjFieldGroupComponent, KjFieldHelpComponent, KjFieldLabelComponent, KjFileUploadComponent, KjFilterCellOutlet, KjFormActionsComponent, KjFormComponent, KjFormSummaryComponent, KjIconGalleryExample, KjIconUsageExample, KjInputComponent, KjInputGroupAddonComponent, KjInputGroupComponent, KjInputMaskComponent, KjInputMaskCreditCardExample, KjInputMaskCustomTokensExample, KjInputMaskDateExample, KjInputMaskExample, KjInputMaskUsageExample, KjInputMaskValidationExample, KjInputOtpComponent, KjKbdComponent, KjLinkComponent, KjListComponent, KjListItemComponent, KjMenubarComponent, KjMenubarItemComponent, KjNumberEditor, KjNumberFilter, KjNumberInputComponent, KjOptionComponent, KjOverlayBadgeComponent, KjOverlayBadgeContentComponent, KjPaginationComponent, KjPaginationDefaultComponent, KjPaginationEllipsisComponent, KjPaginationFirstComponent, KjPaginationInfoComponent, KjPaginationItemComponent, KjPaginationLastComponent, KjPaginationNextComponent, KjPaginationPreviousComponent, KjPasswordInputComponent, KjPopoverComponent, KjProgressBarComponent, KjPromptInput, KjRadioComponent, KjRadioGroupComponent, KjRichTextEditorComponent, KjSelectComponent, KjSelectEditor, KjSelectFilter, KjSheetComponent, KjSkeletonComponent, KjSkipLinkComponent, KjSliderComponent, KjSpeedDialActionComponent, KjSpeedDialActionsComponent, KjSpeedDialComponent, KjSpeedDialTriggerComponent, KjSpinnerComponent, KjStepComponent, KjStepContentComponent, KjStepLabelComponent, KjStepperComponent, KjStepperNextComponent, KjStepperPreviousComponent, KjStepperResetComponent, KjTabComponent, KjTabListComponent, KjTabPanelComponent, KjTableComponent, KjTablePaginationComponent, KjTableSidePanelComponent, KjTableSidePanelContent, KjTableStatusBarComponent, KjTableToolbarComponent, KjTableVirtual, KjTabsComponent, KjTagComponent, KjTagListComponent, KjTagRemoveComponent, KjTextEditor, KjTextFilter, KjTextareaComponent, KjTimePickerComponent, KjToastCloseComponent, KjToastComponent, KjToastViewportComponent, KjToastWrapperComponent, KjToggleComponent, KjTooltipComponent, KjTreeSelectComponent, KjTreeSelectNodeComponent, LUCIDE_ICON_NAMES, bold, bulletList, codeBlock, copyToClipboard, defaultFeatures, downloadString, exportCsv, exportJson, heading, history, image, inlineCode, italic, link, markdownShortcuts, orderedList, provideLucideIcons, quote, renderMarkdown, strike, toTsv, underline };
18004
20510
  //# sourceMappingURL=kouji-ui-components.mjs.map