@kaufmann-lab/ui 0.1.17 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/fesm2022/kaufmann-lab-ui-auth.mjs +322 -0
- package/fesm2022/kaufmann-lab-ui-auth.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-business.mjs +453 -0
- package/fesm2022/kaufmann-lab-ui-business.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-core.mjs +5906 -0
- package/fesm2022/kaufmann-lab-ui-core.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-map.mjs +1637 -0
- package/fesm2022/kaufmann-lab-ui-map.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-mobile.mjs +92 -0
- package/fesm2022/kaufmann-lab-ui-mobile.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui-shared.mjs +269 -0
- package/fesm2022/kaufmann-lab-ui-shared.mjs.map +1 -0
- package/fesm2022/kaufmann-lab-ui.mjs +23 -8472
- package/fesm2022/kaufmann-lab-ui.mjs.map +1 -1
- package/kaufmann-lab-ui-0.1.18.tgz +0 -0
- package/package.json +25 -1
- package/types/kaufmann-lab-ui-auth.d.ts +240 -0
- package/types/kaufmann-lab-ui-business.d.ts +298 -0
- package/types/kaufmann-lab-ui-core.d.ts +3288 -0
- package/types/kaufmann-lab-ui-map.d.ts +631 -0
- package/types/kaufmann-lab-ui-mobile.d.ts +53 -0
- package/types/kaufmann-lab-ui-shared.d.ts +154 -0
- package/types/kaufmann-lab-ui.d.ts +5 -4631
- package/fesm2022/mapbox-gl-csp.worker.js +0 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kaufmann-lab-ui-business.mjs","sources":["../../../projects/ui/business/src/lib/company-selector/CompanySelector.ts","../../../projects/ui/business/src/lib/company-selector/CompanySelector.html","../../../projects/ui/business/src/lib/quote-picker/QuotePicker.ts","../../../projects/ui/business/src/lib/quote-picker/QuotePicker.html","../../../projects/ui/business/src/lib/reserve-block/ReserveBlock.ts","../../../projects/ui/business/src/lib/reserve-block/ReserveBlock.html","../../../projects/ui/business/src/lib/vehicle-header/VehicleHeader.ts","../../../projects/ui/business/src/lib/vehicle-header/VehicleHeader.html","../../../projects/ui/business/src/public-api.ts","../../../projects/ui/business/src/kaufmann-lab-ui-business.ts"],"sourcesContent":["import { Component, input, output } from '@angular/core';\nimport { Divider, Select, Text } from '@kaufmann-lab/ui/core';\n\n/** Metadato clave mostrado junto al selector (RUC, identificación, sucursal). */\nexport interface CompanySelectorMeta {\n label: string;\n value: string;\n}\n\n/**\n * Conmutador de empresa activa con metadatos clave (página 32) — encabeza\n * la pantalla de inicio del portal. Compone `kf-select` para el propio\n * selector (mismo panel propio, sin `<select>` nativo) y proyecta hasta 3\n * pares label/valor (RUC, Identificación, Sucursal en el ejemplo del PDF).\n *\n * <kf-company-selector\n * label=\"Selecciona empresa\"\n * [companies]=\"['TRANSPORTES DEL SUR S.A.C.', 'ANDES MAQ LTDA.']\"\n * [value]=\"activeCompany()\"\n * (valueChange)=\"activeCompany.set($event)\"\n * [meta]=\"[\n * { label: 'RUC', value: '20448712359' },\n * { label: 'Identificación', value: '0004002232' },\n * { label: 'Sucursal', value: 'Sucursal Norte' },\n * ]\"\n * />\n */\n@Component({\n selector: 'kf-company-selector',\n imports: [Divider, Select, Text],\n templateUrl: './CompanySelector.html',\n styleUrl: './CompanySelector.css',\n})\nexport class CompanySelector {\n readonly label = input('Selecciona empresa');\n readonly companies = input.required<string[]>();\n readonly value = input<string>();\n readonly meta = input<CompanySelectorMeta[]>([]);\n\n readonly valueChange = output<string>();\n}\n","<kf-select\n class=\"kf-company-selector__select\"\n [label]=\"label()\"\n [options]=\"companies()\"\n [value]=\"value()\"\n (valueChange)=\"valueChange.emit($event)\"\n/>\n@if (meta().length) {\n <div class=\"kf-company-selector__meta\">\n @for (item of meta(); track item.label; let last = $last) {\n <div class=\"kf-company-selector__meta-item\">\n <kf-text as=\"span\" variant=\"overline\">{{ item.label }}</kf-text>\n <span class=\"kf-company-selector__meta-value\">{{ item.value }}</span>\n </div>\n @if (!last) {\n <kf-divider orientation=\"vertical\" />\n }\n }\n </div>\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n TemplateRef,\n afterNextRender,\n computed,\n inject,\n input,\n model,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport {\n DataTable,\n DataTableColumn,\n EmptyState,\n Icon,\n IconName,\n Modal,\n Pagination,\n} from '@kaufmann-lab/ui/core';\nimport { matchMediaSignal, normalizeForSearch } from '@kaufmann-lab/ui/shared';\n\n/** Reexportado tal cual — el picker no inventa un concepto de columna propio,\n * usa el mismo `DataTableColumn` que ya consume `kf-data-table`. */\nexport type { DataTableColumn };\n\n/** Chip de filtro genérico con contador — nunca hardcodeado a un dominio\n * concreto (ej. estado de una cotización); el consumidor decide qué\n * representa cada `value` y cómo mapea sus items contra él vía `predicate`.\n *\n * Bug real corregido: la primera versión leía `item.status`/`item.chip` por\n * nombre de campo mágico en vez de un `predicate` — colisionaba con\n * dominios donde `status` ya significa otra cosa (ej. `Quote.status` en\n * `web-otd-frontend` es 'ok'|'error'|'warn' de aprobación, no \"tiene saldo\n * pendiente\"). Un chip \"Con saldo pendiente\" sobre cotizaciones terminaba\n * filtrando por un campo que no tenía nada que ver, mostrando 0 resultados\n * siempre. `predicate` es explícito y no depende de convenciones de nombre. */\nexport interface QuotePickerChip<T = unknown> {\n value: string;\n label: string;\n count: number;\n predicate: (item: T) => boolean;\n}\n\n/** Una opción del dropdown \"Ordenar por\", visible solo en `variant=\"modal\"`. */\nexport interface QuotePickerSortOption {\n value: string;\n label: string;\n}\n\n/** Filas visibles en el preview acotado (modo `inline`, volumen alto) antes del fade + CTA. */\nconst PREVIEW_ROWS = 5;\n/** Filas por página en la tabla del modo `modal`. */\nconst PAGE_SIZE = 10;\n\n/**\n * Selector de un ítem \"rico\" de una lista buscable/filtrable — generalización\n * del patrón \"elegir una cotización\" de Pagos y Facturas de OTD, pero sin\n * ningún acoplamiento a `Quote`: todo el contenido de cada fila/card llega\n * por `columns` (mismo `DataTableColumn` de `kf-data-table`, reexportado acá\n * en vez de duplicar el concepto) + `cellTemplates` para contenido custom\n * (thumbnail, monto formateado, etc. — mismo mecanismo `TemplateRef` +\n * `ngTemplateOutlet` que ya usa `kf-data-table`).\n *\n * Un solo componente, dos contenedores (`variant: 'inline' | 'modal'`), UNA\n * sola lógica de búsqueda/filtro/orden interna. Nunca dos implementaciones\n * paralelas: el riesgo real de eso es que un fix de filtro se aplique en un\n * modo y se olvide en el otro. Los `computed()` de más abajo\n * (`filteredItems`, `sortedItems`) son la ÚNICA fuente de verdad para ambos\n * `variant`; lo que cambia entre inline y modal es solo qué contenedor\n * envuelve esos datos ya resueltos.\n *\n * ## Modo `inline` (default)\n * Trigger a ANCHO COMPLETO (nunca una caja angosta de ancho fijo) que\n * muestra el ítem activo colapsado — thumbnail, id + modelo, unidades +\n * fecha + monto, CTA \"Cambiar cotización\" con chevron-down. Al click, el\n * panel se expande INLINE (empuja el contenido de abajo, nunca flota\n * encima) con buscador propio + chips de filtro + un grid de 2 columnas (1\n * en mobile, breakpoint `max-width: 900px` vía `matchMediaSignal` — mismo\n * mecanismo que ya usa el resto de la librería para decisiones de layout en\n * TypeScript, no solo CSS). Por encima de `expandThreshold` resultados\n * visibles, el panel recorta a un preview de `PREVIEW_ROWS` filas con un\n * fade inferior y un botón dashed \"Ver las N en pantalla completa\" que\n * emite `expandToModal` — el picker no decide qué pasa después (típicamente\n * el consumidor pone `variant` en `'modal'` y `open` en `true`).\n *\n * ## Modo `modal`\n * Mismo buscador, mismos chips, misma lógica de filtrado — compone\n * `kf-modal` (proyectando el contenido) en vez de reimplementar un\n * `<dialog>` a mano: la API de `Modal` (`[(open)]`, cierre con\n * Escape/backdrop/botón vía `<dialog>` nativo) ya cubre exactamente lo que\n * este modo necesita. Compone también `kf-data-table` para la tabla\n * completa (columnas configurables, fade de overflow horizontal ya\n * resuelto ahí) y `kf-pagination` para paginar — ninguno de los tres se\n * reimplementa. Agrega un dropdown propio de \"Ordenar por\" (calibrado\n * visualmente contra el trigger de `kf-select`, pero compacto: `kf-select`\n * fuerza un ancho fijo de 240px pensado para formularios, no para una\n * barra de herramientas de tabla — ver JSDoc de `sortOpen` más abajo).\n *\n * En mobile, `kf-data-table[cardable]` con `defaultView` forzado a\n * `'cards'` decide la vista (mismo criterio que `matchMediaSignal` ya\n * resolvió en otros consumidores): dentro de un modal a pantalla completa\n * no tiene sentido ofrecer un toggle tabla/cards que en mobile daría una\n * tabla angosta con scroll horizontal.\n *\n * DEUDA TÉCNICA CONOCIDA (confirmada con el usuario, ver CHANGELOG.md): el\n * diseño validado con mockups pedía que en mobile el modal ocupe el 100%\n * de la pantalla (botón \"atrás\", sin overlay centrado) — `kf-modal` no\n * tiene ese modo, así que hoy en mobile se ve como un diálogo centrado\n * angosto (`width: min(480px, ...)`). Es funcional (cards legibles,\n * búsqueda, chips, paginación), solo visualmente distinto del mockup.\n *\n * <kf-quote-picker\n * [items]=\"quotes()\"\n * [columns]=\"columns\"\n * [selectedId]=\"selectedQuoteId()\"\n * [idKey]=\"(q) => q.id\"\n * [chips]=\"statusChips()\"\n * [cellTemplates]=\"{ photo: photoCell(), amount: amountCell() }\"\n * (selectedIdChange)=\"selectedQuoteId.set($event)\"\n * (expandToModal)=\"variant.set('modal'); open.set(true)\"\n * />\n */\n@Component({\n selector: 'kf-quote-picker',\n imports: [NgTemplateOutlet, Icon, Modal, DataTable, EmptyState, Pagination],\n templateUrl: './QuotePicker.html',\n styleUrl: './QuotePicker.css',\n})\nexport class QuotePicker<T = unknown> {\n readonly items = input.required<T[]>();\n readonly columns = input.required<DataTableColumn[]>();\n readonly selectedId = input<string | null>(null);\n readonly idKey = input.required<(item: T) => string>();\n\n /**\n * Mapa `columnKey -> TemplateRef`, mismo mecanismo que `kf-data-table`\n * (`ngTemplateOutlet` + contexto `{ $implicit: item, index }`) — se\n * reenvía tal cual a la tabla interna del modo `modal`, y se usa\n * directamente en el grid de cards del modo `inline`. Un solo mapa para\n * ambos modos, consistente con la regla de \"una sola lógica interna\".\n */\n readonly cellTemplates = input<\n Record<string, TemplateRef<{ $implicit: T; index: number }>> | undefined\n >();\n\n readonly chips = input<QuotePickerChip<T>[]>([]);\n readonly sortOptions = input<QuotePickerSortOption[]>([]);\n readonly sort = model<string | null>(null);\n\n /**\n * Umbral de volumen alto — el consumidor decide el número exacto, nunca\n * hardcodeado a \"cotizaciones\" ni a ningún caso de uso puntual. Default\n * 15 según el diseño validado con mockups.\n */\n readonly expandThreshold = input(15);\n\n readonly variant = input<'inline' | 'modal'>('inline');\n /** Visibilidad del modo `modal`, two-way — mismo patrón que `[(open)]` de `kf-modal`. */\n readonly open = model(false);\n\n readonly title = input('Cambiar cotización');\n readonly searchPlaceholder = input('Buscar…');\n /** Ícono de placeholder cuando ninguna columna `cardRole: 'media'` resuelve\n * un thumbnail real vía `cellTemplates` — el picker no asume qué dominio\n * consume (cotización, vehículo, cliente...), así que no hardcodea un\n * ícono fijo. Default `'file'` solo por no dejar el input sin valor. */\n readonly placeholderIcon = input<IconName>('file');\n\n readonly selectedIdChange = output<string>();\n /** Disparado al superar `expandThreshold` en modo inline; el consumidor decide pasar a `modal`. */\n readonly expandToModal = output<void>();\n\n protected readonly searchQuery = signal('');\n protected readonly activeChip = signal<string | null>(null);\n protected readonly expanded = signal(false);\n protected readonly page = signal(1);\n protected readonly sortOpen = signal(false);\n\n /**\n * Mismo breakpoint (`max-width: 900px`) que el resto de la librería usa\n * para decisiones de layout en TypeScript (no solo CSS) — ver\n * `matchMediaSignal`. Decide 1 vs. 2 columnas en el grid inline, y tabla\n * vs. cards apiladas dentro del modal.\n */\n protected readonly isMobile = matchMediaSignal('(max-width: 900px)');\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly previewScrollEl = viewChild<ElementRef<HTMLElement>>('previewScroll');\n\n /** Mismo mecanismo de fade que `kf-data-table` — ver comentario en QuotePicker.css. */\n protected readonly canFadeBottom = signal(false);\n\n readonly selectedItem = computed(() =>\n this.items().find((item) => this.idKey()(item) === this.selectedId()),\n );\n\n /** Filtro por texto (buscador propio) + filtro por chip activo, en ese orden. */\n protected readonly filteredItems = computed<T[]>(() => {\n const query = normalizeForSearch(this.searchQuery().trim());\n const chipValue = this.activeChip();\n const chip = chipValue ? this.chips().find((c) => c.value === chipValue) : undefined;\n const idKeyFn = this.idKey();\n const cols = this.columns();\n\n return this.items().filter((item) => {\n if (chip && !chip.predicate(item)) {\n return false;\n }\n if (!query) {\n return true;\n }\n const haystack = cols\n .map((column) => this.cellText(item, column))\n .concat(idKeyFn(item))\n .join(' ');\n return normalizeForSearch(haystack).includes(query);\n });\n });\n\n /**\n * Orden solo tiene efecto visible en modo `modal` (el diseño validado no\n * pide dropdown de orden en inline) — se calcula igual en ambos casos\n * porque es la MISMA lógica interna; en inline `sort()` simplemente se\n * queda en `null` salvo que el consumidor lo setee explícitamente.\n */\n protected readonly sortedItems = computed<T[]>(() => {\n const sortValue = this.sort();\n const items = this.filteredItems();\n if (!sortValue) {\n return items;\n }\n const [key, direction] = sortValue.split(':') as [string, 'asc' | 'desc' | undefined];\n const sorted = [...items].sort((a, b) => {\n const va = (a as Record<string, unknown>)[key];\n const vb = (b as Record<string, unknown>)[key];\n if (va === vb) {\n return 0;\n }\n return (va as string | number) > (vb as string | number) ? 1 : -1;\n });\n return direction === 'desc' ? sorted.reverse() : sorted;\n });\n\n /** Por encima del umbral, el preview inline se recorta salvo que el usuario ya haya expandido. */\n protected readonly isHighVolume = computed(\n () => this.sortedItems().length > this.expandThreshold(),\n );\n\n protected readonly previewItems = computed<T[]>(() => {\n const all = this.sortedItems();\n if (!this.isHighVolume() || this.expanded()) {\n return all;\n }\n return all.slice(0, PREVIEW_ROWS);\n });\n\n protected readonly pages = computed(() =>\n Math.max(Math.ceil(this.sortedItems().length / PAGE_SIZE), 1),\n );\n\n protected readonly pagedItems = computed<T[]>(() => {\n const start = (this.page() - 1) * PAGE_SIZE;\n return this.sortedItems().slice(start, start + PAGE_SIZE);\n });\n\n protected readonly sortLabel = computed(() => {\n const current = this.sortOptions().find((option) => option.value === this.sort());\n return current?.label ?? 'Ordenar por';\n });\n\n constructor() {\n afterNextRender(() => {\n const el = this.previewScrollEl()?.nativeElement;\n if (!el) {\n return;\n }\n const update = () => this.updateFadeState(el);\n update();\n el.addEventListener('scroll', update, { passive: true });\n const observer = new ResizeObserver(update);\n observer.observe(el);\n this.destroyRef.onDestroy(() => {\n el.removeEventListener('scroll', update);\n observer.disconnect();\n });\n });\n }\n\n private updateFadeState(el: HTMLElement): void {\n // 1px de margen por el mismo motivo que en DataTable: subpíxeles de\n // scroll dejarían el fade \"prendido\" en un preview que ya llegó al final.\n this.canFadeBottom.set(el.scrollHeight - el.clientHeight - el.scrollTop > 1);\n }\n\n private cellText(item: T, column: DataTableColumn): string {\n const value = (item as Record<string, unknown>)[column.key];\n return value === null || value === undefined ? '' : String(value);\n }\n\n toggleExpandedPanel(): void {\n this.expanded.set(!this.expanded());\n }\n\n onSearchInput(event: Event): void {\n this.searchQuery.set((event.target as HTMLInputElement).value);\n this.page.set(1);\n }\n\n selectChip(value: string): void {\n this.activeChip.set(this.activeChip() === value ? null : value);\n this.page.set(1);\n }\n\n select(item: T): void {\n const id = this.idKey()(item);\n // El panel se cierra siempre al elegir (haya cambiado el id o no) —\n // mismo comportamiento esperado de cualquier selector, ej. `kf-select`\n // cierra su panel al elegir opción; dejarle esa responsabilidad al\n // consumidor sería una carga que ningún otro componente de la\n // librería le pide.\n this.expanded.set(false);\n if (id === this.selectedId()) {\n return;\n }\n this.selectedIdChange.emit(id);\n }\n\n onItemKeydown(event: KeyboardEvent, item: T): void {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.select(item);\n }\n }\n\n onSeeAll(): void {\n this.expandToModal.emit();\n }\n\n onTableRowClick(event: { row: T; index: number }): void {\n this.select(event.row);\n }\n\n toggleSort(): void {\n this.sortOpen.update((open) => !open);\n }\n\n setSort(value: string): void {\n this.sort.set(this.sort() === value ? null : value);\n this.sortOpen.set(false);\n }\n\n trackItem(item: T, index: number): string | number {\n const idKeyFn = this.idKey();\n return idKeyFn ? idKeyFn(item) : index;\n }\n\n /** Arrow function como campo (no un método) para que `[rowKey]` reciba\n * una referencia ESTABLE entre change detections — `trackItem.bind(this)`\n * en el template recrearía una función nueva en cada ciclo, invalidando\n * cualquier optimización de `kf-data-table` que dependa de identidad. */\n protected readonly rowKeyFn = (item: T, index: number): string | number =>\n this.trackItem(item, index);\n\n protected cellValue(item: T, column: DataTableColumn): string {\n return this.cellText(item, column);\n }\n\n protected readonly mediaColumn = computed(() =>\n this.columns().find((c) => c.cardRole === 'media'),\n );\n protected readonly titleColumn = computed(() =>\n this.columns().find((c) => c.cardRole === 'title'),\n );\n protected readonly fieldColumns = computed(() =>\n this.columns().filter((c) => !c.cardRole || c.cardRole === 'field'),\n );\n}\n","@if (variant() === 'inline') {\n <div class=\"kf-quote-picker__inline\">\n <!-- Trigger colapsado (default): ancho completo, nunca una caja angosta. -->\n <button\n type=\"button\"\n class=\"kf-quote-picker__trigger\"\n [attr.aria-expanded]=\"expanded()\"\n (click)=\"toggleExpandedPanel()\"\n >\n <span class=\"kf-quote-picker__thumb\">\n @if (mediaColumn(); as media) {\n @if (cellTemplates()?.[media.key]; as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: selectedItem(), index: 0 }\"\n />\n }\n } @else {\n <kf-icon [name]=\"placeholderIcon()\" size=\"md\" />\n }\n </span>\n @if (selectedItem(); as item) {\n <span class=\"kf-quote-picker__trigger-summary\">\n @if (titleColumn(); as title) {\n <span class=\"kf-quote-picker__trigger-field kf-quote-picker__trigger-field--title\">{{\n cellValue(item, title)\n }}</span>\n }\n <!--\n En mobile solo se muestra el título (ID) — mostrar los 5 campos\n en una sola línea de ~90px de ancho real corta el texto sin\n elipsis a mitad del segundo campo (bug real medido:\n scrollWidth=519 vs. clientWidth=87 en 390px). El resto de los\n campos siguen disponibles en el panel expandido y en el modal,\n donde sí hay espacio horizontal.\n -->\n @if (!isMobile()) {\n @for (col of fieldColumns(); track col.key) {\n <span class=\"kf-quote-picker__trigger-sep\" aria-hidden=\"true\">·</span>\n <span class=\"kf-quote-picker__trigger-field\">{{ cellValue(item, col) }}</span>\n }\n }\n </span>\n } @else {\n <span class=\"kf-quote-picker__trigger-summary kf-quote-picker__trigger-summary--empty\"\n >Sin selección</span\n >\n }\n <span class=\"kf-quote-picker__trigger-action\">\n {{ expanded() ? 'Cerrar' : title() }}\n <kf-icon\n name=\"chevron-down\"\n size=\"sm\"\n class=\"kf-quote-picker__chevron\"\n [class.kf-quote-picker__chevron--open]=\"expanded()\"\n />\n </span>\n </button>\n\n @if (expanded()) {\n <div class=\"kf-quote-picker__panel\">\n <div class=\"kf-quote-picker__toolbar\">\n <div class=\"kf-quote-picker__search\">\n <kf-icon name=\"search\" size=\"sm\" />\n <input\n type=\"text\"\n class=\"kf-quote-picker__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n />\n </div>\n @for (chip of chips(); track chip.value) {\n <button\n type=\"button\"\n class=\"kf-quote-picker__chip\"\n [class.kf-quote-picker__chip--active]=\"activeChip() === chip.value\"\n (click)=\"selectChip(chip.value)\"\n >\n {{ chip.label }} ({{ chip.count }})\n </button>\n }\n </div>\n\n <div class=\"kf-quote-picker__results-wrap\">\n <div #previewScroll class=\"kf-quote-picker__results\" role=\"listbox\">\n @for (item of previewItems(); track trackItem(item, $index)) {\n <button\n type=\"button\"\n class=\"kf-quote-picker__result\"\n [class.kf-quote-picker__result--active]=\"idKey()(item) === selectedId()\"\n role=\"option\"\n [attr.aria-selected]=\"idKey()(item) === selectedId()\"\n (click)=\"select(item)\"\n (keydown)=\"onItemKeydown($event, item)\"\n >\n <span class=\"kf-quote-picker__thumb kf-quote-picker__thumb--sm\">\n @if (mediaColumn(); as media) {\n @if (cellTemplates()?.[media.key]; as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: item, index: $index }\"\n />\n }\n } @else {\n <kf-icon [name]=\"placeholderIcon()\" size=\"sm\" />\n }\n </span>\n @if (titleColumn(); as title) {\n <span\n class=\"kf-quote-picker__result-field kf-quote-picker__result-field--title\"\n >{{ cellValue(item, title) }}</span\n >\n }\n <!--\n Wrapper propio (no los spans sueltos) para los campos\n secundarios: en mobile necesita saltar de línea COMPLETO\n (mismo criterio que \"unidades\" no debe competir con\n \"modelo\" en la primera línea) — `flex-basis: 100%` en un\n solo elemento fuerza ese salto sin tener que asumir cuál\n de los N campos genéricos es el más corto o el más largo.\n -->\n <span class=\"kf-quote-picker__result-fields\">\n @for (col of fieldColumns(); track col.key; let first = $first) {\n <span\n class=\"kf-quote-picker__result-field\"\n [class.kf-quote-picker__result-field--primary]=\"first\"\n >{{ cellValue(item, col) }}</span\n >\n }\n </span>\n </button>\n } @empty {\n <p class=\"kf-quote-picker__empty\">Sin resultados para esta búsqueda.</p>\n }\n </div>\n @if (canFadeBottom()) {\n <div class=\"kf-quote-picker__fade\" aria-hidden=\"true\"></div>\n }\n </div>\n\n @if (isHighVolume()) {\n <button type=\"button\" class=\"kf-quote-picker__see-all\" (click)=\"onSeeAll()\">\n Ver las {{ sortedItems().length }} en pantalla completa\n </button>\n }\n </div>\n }\n </div>\n} @else {\n <kf-modal [(open)]=\"open\" [title]=\"title()\" [dismissible]=\"true\">\n <div class=\"kf-quote-picker__modal-toolbar\">\n <div class=\"kf-quote-picker__search\">\n <kf-icon name=\"search\" size=\"sm\" />\n <input\n type=\"text\"\n class=\"kf-quote-picker__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n />\n </div>\n <div class=\"kf-quote-picker__modal-filters\">\n <div class=\"kf-quote-picker__modal-chips\">\n @for (chip of chips(); track chip.value) {\n <button\n type=\"button\"\n class=\"kf-quote-picker__chip\"\n [class.kf-quote-picker__chip--active]=\"activeChip() === chip.value\"\n (click)=\"selectChip(chip.value)\"\n >\n {{ chip.label }} ({{ chip.count }})\n </button>\n }\n </div>\n @if (sortOptions().length > 0) {\n <div class=\"kf-quote-picker__sort\">\n <button\n type=\"button\"\n class=\"kf-quote-picker__sort-trigger\"\n [attr.aria-expanded]=\"sortOpen()\"\n (click)=\"toggleSort()\"\n >\n <kf-icon name=\"sort\" size=\"sm\" />\n {{ sortLabel() }}\n <kf-icon name=\"chevron-down\" size=\"sm\" />\n </button>\n @if (sortOpen()) {\n <div class=\"kf-quote-picker__sort-panel\">\n @for (option of sortOptions(); track option.value) {\n <button\n type=\"button\"\n class=\"kf-quote-picker__sort-option\"\n [class.kf-quote-picker__sort-option--active]=\"sort() === option.value\"\n (click)=\"setSort(option.value)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <kf-data-table\n [columns]=\"columns()\"\n [rows]=\"pagedItems()\"\n [cardable]=\"true\"\n [defaultView]=\"isMobile() ? 'cards' : 'table'\"\n [cellTemplates]=\"cellTemplates()\"\n [rowKey]=\"rowKeyFn\"\n (rowClick)=\"onTableRowClick($event)\"\n >\n <kf-empty-state empty icon=\"file\">Sin resultados para esta búsqueda.</kf-empty-state>\n @if (sortedItems().length > 0) {\n <kf-pagination footer [page]=\"page()\" [pages]=\"pages()\" (pageChange)=\"page.set($event)\">\n {{ sortedItems().length }} resultados\n </kf-pagination>\n }\n </kf-data-table>\n </kf-modal>\n}\n","import { booleanAttribute, Component, input } from '@angular/core';\nimport { Icon, Link } from '@kaufmann-lab/ui/core';\n\n/**\n * Estado vacío de reservas en taller con llamada a agendar (página 36):\n * barra de estado vacío arriba (\"No tienes reservas de taller\"), panel de\n * invitación al medio (ícono en círculo azul, título, descripción, link) y\n * una fila de dos acciones al pie — un slot `[actions]` proyectado, para no\n * acoplar el componente a botones fijos.\n *\n * Distinto de `kf-empty-state` genérico: este combina la barra + la\n * invitación + las acciones como un bloque compuesto propio del dominio\n * \"taller\", no un placeholder de una sola pieza.\n *\n * `grow` estira el panel de invitación para llenar el espacio vertical\n * disponible — solo cuando el consumidor comparte fila con una tarjeta más\n * alta (ej. junto a \"Total de vehículos\"); en un lugar sin esa presión\n * (home, debajo del carousel) se deja en su alto natural.\n *\n * <kf-reserve-block emptyLabel=\"No tienes reservas de taller\" grow\n * title=\"¿Necesitas mantención?\" description=\"Tenemos la mejor red de talleres.\"\n * actionLabel=\"Agenda tu reserva aquí\" actionHref=\"/taller/agendar\">\n * <kf-button actions icon=\"calendar\">Reservar hora</kf-button>\n * <kf-button actions variant=\"outline\" icon=\"list\">Ver agenda</kf-button>\n * </kf-reserve-block>\n */\n@Component({\n selector: 'kf-reserve-block',\n imports: [Icon, Link],\n templateUrl: './ReserveBlock.html',\n styleUrl: './ReserveBlock.css',\n})\nexport class ReserveBlock {\n readonly emptyLabel = input('No tienes reservas de taller');\n readonly title = input.required<string>();\n readonly description = input<string>();\n readonly actionLabel = input<string>();\n readonly actionHref = input<string>();\n /** La invitación se estira para llenar la tarjeta (ej. junto a \"Total de vehículos\"). */\n readonly grow = input(false, { transform: booleanAttribute });\n}\n","<div class=\"kf-reserve-block__empty\">\n <kf-icon name=\"calendar\" size=\"sm\" />\n <span>{{ emptyLabel() }}</span>\n</div>\n<div class=\"kf-reserve-block__invite\" [class.kf-reserve-block__invite--grow]=\"grow()\">\n <span class=\"kf-reserve-block__invite-icon\">\n <kf-icon name=\"tool\" size=\"md\" />\n </span>\n <div class=\"kf-reserve-block__invite-text\">\n <span class=\"kf-reserve-block__invite-title\">{{ title() }}</span>\n @if (description()) {\n <span class=\"kf-reserve-block__invite-description\">{{ description() }}</span>\n }\n @if (actionLabel()) {\n <kf-link class=\"kf-reserve-block__invite-action\" [href]=\"actionHref() || '#'\" showArrow>\n {{ actionLabel() }}\n </kf-link>\n }\n </div>\n</div>\n<div class=\"kf-reserve-block__actions\">\n <ng-content select=\"[actions]\" />\n</div>\n","import { Component, input } from '@angular/core';\nimport { Icon, IconName, Text } from '@kaufmann-lab/ui/core';\n\n/**\n * Estado puntual mostrado junto a la identidad del vehículo (ej. \"En ruta\",\n * \"Mantenimiento\", \"Fuera de servicio\"). `tone` define el color semántico:\n * \"crit\" no tiene token propio en base.css, se mapea a var(--kf-color-error).\n */\nexport interface VehicleHeaderStatus {\n label: string;\n tone?: 'ok' | 'warn' | 'crit';\n icon?: IconName;\n}\n\n/**\n * Header de identidad de un vehículo de flota: unidad (patente/id), modelo\n * (como badge, no texto plano — página 24: \"ABC-123\" junto a un badge\n * \"TITAN 4X2\"), VIN en fuente mono y un estado opcional. Un área de acciones\n * opcional se proyecta vía `<ng-content select=\"[actions]\">` para no acoplar\n * el componente a un set fijo de botones — el patrón real de la spec es\n * `kf-button variant=\"outline\"` (ej. \"Llamar\", con ícono) + un `primary`\n * (ej. \"Crear Ticket\", con ícono \"+\"):\n *\n * <kf-vehicle-header unit=\"AB123CD\" model=\"Sprinter 415\" vin=\"9BW...\"\n * [status]=\"{ label: 'En ruta', tone: 'ok' }\">\n * <kf-button actions variant=\"outline\" icon=\"phone\">Llamar</kf-button>\n * <kf-button actions icon=\"plus\">Crear Ticket</kf-button>\n * </kf-vehicle-header>\n */\n@Component({\n selector: 'kf-vehicle-header',\n imports: [Icon, Text],\n templateUrl: './VehicleHeader.html',\n styleUrl: './VehicleHeader.css',\n})\nexport class VehicleHeader {\n readonly unit = input.required<string>();\n readonly model = input<string>();\n readonly vin = input<string>();\n readonly status = input<VehicleHeaderStatus>();\n}\n","<div class=\"kf-vehicle-header__identity\">\n <span class=\"kf-vehicle-header__unit\">{{ unit() }}</span>\n @if (model()) {\n <span class=\"kf-vehicle-header__model\">\n <kf-text as=\"span\" variant=\"overline-strong\">{{ model() }}</kf-text>\n </span>\n }\n @if (vin()) {\n <span class=\"kf-vehicle-header__vin\">VIN: {{ vin() }}</span>\n }\n</div>\n\n@if (status(); as currentStatus) {\n <span\n class=\"kf-vehicle-header__status\"\n [class]=\"'kf-vehicle-header__status--' + (currentStatus.tone ?? 'ok')\"\n >\n @if (currentStatus.icon; as iconName) {\n <kf-icon [name]=\"iconName\" size=\"sm\" />\n }\n {{ currentStatus.label }}\n </span>\n}\n\n<div class=\"kf-vehicle-header__actions\">\n <ng-content select=\"[actions]\" />\n</div>\n","/*\n * Public API Surface of ui/business — entry point secundario, `@kaufmann-lab/ui/business`.\n *\n * Componentes que modelan un concepto de negocio real de Kaufmann (una\n * cotización, una reserva de taller, un vehículo de flota, la empresa activa\n * de una sesión), no una preocupación de UI transversal — ver\n * `ENTRY-POINTS.md` en la raíz del repo para el criterio.\n *\n * Consume sus piezas base (`Icon`, `Text`, `Select`, `DataTable`, etc.) desde\n * `'@kaufmann-lab/ui/core'` y los helpers desde `'@kaufmann-lab/ui/shared'`,\n * nunca desde la raíz `'@kaufmann-lab/ui'` (agregador que depende de todos\n * los entry points — importarla desde acá cerraría un ciclo) ni por ruta\n * relativa cruzando la frontera entre entry points (ng-packagr calcula un\n * `rootDir` propio por entry point y rechaza archivos fuente fuera de él).\n *\n * La raíz `'@kaufmann-lab/ui'` los reexporta, así que\n * `import { QuotePicker } from '@kaufmann-lab/ui'` sigue funcionando igual.\n */\n\nexport * from './lib/company-selector/CompanySelector';\nexport * from './lib/quote-picker/QuotePicker';\nexport * from './lib/reserve-block/ReserveBlock';\nexport * from './lib/vehicle-header/VehicleHeader';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|