@joanroucoux/cairn-ui 0.11.1 → 0.11.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.3
4
+
5
+ ### Fixed
6
+
7
+ - A `button[uiRowLink]` and an available `ui-row` show the pointer cursor, like a link row.
8
+
9
+ ## 0.11.2
10
+
11
+ ### Fixed
12
+
13
+ - A tall `ui-dialog` sheet on mobile stops below the status bar of a home screen web app on iPhone (`env(safe-area-inset-top)`).
14
+
3
15
  ## 0.11.1
4
16
 
5
17
  ### Fixed
@@ -280,7 +280,7 @@ var UiDialog = class UiDialog {
280
280
  headerClasses = computed(() => `flex ${this.description() ? "items-start" : "items-center"} gap-2 pl-4 max-lg:touch-none lg:gap-3 ${this.spec().header} ${this.closeLabel() ? "pr-2 lg:pr-4" : "pr-4 lg:pr-6"} ${this.hairlines() ? "shadow-[inset_0_-1px_0_var(--hairline)]" : ""}`, ...ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []);
281
281
  crossClasses = "rounded-pill lg:rounded-control grid size-11 flex-none cursor-pointer place-items-center text-(--muted-foreground) transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out outline-none focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-(--ring) active:scale-(--press-scale) active:bg-(--soft) disabled:pointer-events-none disabled:opacity-40 lg:size-9 lg:hover:bg-(--glow) lg:hover:text-(--foreground)";
282
282
  footerClasses = computed(() => `max-lg:[&>[ui-button]]:text-body flex justify-end gap-2 px-4 pb-[calc(8px+env(safe-area-inset-bottom))] max-lg:flex-col-reverse max-lg:[&>[ui-button]]:h-[50px] max-lg:[&>[ui-button]]:w-full lg:px-6 ${this.spec().footer} ${this.hairlines() ? "shadow-[inset_0_1px_0_var(--hairline)]" : ""}`, ...ngDevMode ? [{ debugName: "footerClasses" }] : /* istanbul ignore next */ []);
283
- classes = computed(() => `open:flex w-full flex-col overflow-hidden m-auto mt-auto max-lg:max-h-[calc(100dvh-2rem)] lg:max-h-[calc(100dvh-96px)] max-lg:mb-0 max-lg:max-w-none max-lg:rounded-b-none lg:max-w-(--dialog-width) rounded-container bg-(--card) text-(--foreground) outline-none shadow-[0_0_0_1px_var(--border),0_24px_64px_rgb(0_0_0/0.24)] max-lg:shadow-[0_-1px_0_var(--border),0_-12px_32px_rgb(0_0_0/0.16)] ${this.stacked() ? "backdrop:bg-black/[0.24]" : "backdrop:bg-black/[0.36]"} ${this.sheet() === "full" ? "max-lg:h-[calc(100dvh-58px)]" : ""}`, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
283
+ classes = computed(() => `open:flex w-full flex-col overflow-hidden m-auto mt-auto max-lg:max-h-[calc(100dvh-2rem-env(safe-area-inset-top))] lg:max-h-[calc(100dvh-96px)] max-lg:mb-0 max-lg:max-w-none max-lg:rounded-b-none lg:max-w-(--dialog-width) rounded-container bg-(--card) text-(--foreground) outline-none shadow-[0_0_0_1px_var(--border),0_24px_64px_rgb(0_0_0/0.24)] max-lg:shadow-[0_-1px_0_var(--border),0_-12px_32px_rgb(0_0_0/0.16)] ${this.stacked() ? "backdrop:bg-black/[0.24]" : "backdrop:bg-black/[0.36]"} ${this.sheet() === "full" ? "max-lg:h-[calc(100dvh-58px)]" : ""}`, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
284
284
  #host = inject(ElementRef);
285
285
  #drag = null;
286
286
  modal;
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-dialog.mjs","names":[],"sources":["../../../projects/ui/dialog/internal/dialog-styles.ts","../../../projects/ui/dialog/internal/dialog-exit.ts","../../../projects/ui/dialog/internal/modal-close.ts","../../../projects/ui/dialog/internal/sheet-drag.ts","../../../projects/ui/dialog/dialog.ts"],"sourcesContent":["export const DIALOG_STYLES = `\ndialog {\n --dialog-ease: var(--ease-sheet);\n transition:\n transform var(--duration-base) var(--dialog-ease),\n overlay var(--duration-base) allow-discrete,\n display var(--duration-base) allow-discrete;\n transform: translateY(var(--drag-y, 0px));\n}\n\ndialog:not([open]) {\n transform: translateY(100%);\n transition-duration: var(--duration-exit);\n}\n\n@starting-style {\n dialog[open] {\n transform: translateY(100%);\n }\n}\n\ndialog[data-dragging] {\n transition: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n dialog {\n transition:\n opacity var(--duration-base) var(--dialog-ease),\n overlay var(--duration-base) allow-discrete,\n display var(--duration-base) allow-discrete;\n opacity: 1;\n }\n\n dialog:not([open]) {\n opacity: 0;\n transform: translateY(var(--drag-y, 0px));\n }\n\n @starting-style {\n dialog[open] {\n opacity: 0;\n transform: translateY(0);\n }\n }\n}\n\n@media (min-width: 64rem) {\n dialog {\n --dialog-ease: var(--ease-out);\n transition:\n opacity var(--duration-base) var(--dialog-ease),\n transform var(--duration-base) var(--dialog-ease),\n overlay var(--duration-base) allow-discrete,\n display var(--duration-base) allow-discrete;\n opacity: 1;\n transform: scale(1);\n }\n\n dialog:not([open]) {\n opacity: 0;\n transform: scale(var(--enter-scale));\n }\n\n @starting-style {\n dialog[open] {\n opacity: 0;\n transform: scale(var(--enter-scale));\n }\n }\n}\n\ndialog::backdrop {\n transition: opacity var(--duration-base) var(--ease-out);\n opacity: 1;\n}\n\ndialog:not([open])::backdrop {\n opacity: 0;\n transition-duration: var(--duration-exit);\n}\n\n@starting-style {\n dialog[open]::backdrop {\n opacity: 0;\n }\n}\n`;\n","const GRACE = 50;\n\nexport function afterExit(element: HTMLElement, done: () => void): () => void {\n const style = getComputedStyle(element);\n const wait = longest(style.transitionDuration) + longest(style.transitionDelay);\n\n if (wait === 0) {\n done();\n return () => undefined;\n }\n\n const onEnd = (event: TransitionEvent): void => {\n if (event.target === element && !event.pseudoElement) {\n cancel();\n done();\n }\n };\n const timer = setTimeout(() => {\n cancel();\n done();\n }, wait + GRACE);\n const cancel = (): void => {\n clearTimeout(timer);\n element.removeEventListener('transitionend', onEnd);\n };\n\n element.addEventListener('transitionend', onEnd);\n\n return cancel;\n}\n\nfunction longest(list: string): number {\n return Math.max(0, ...list.split(',').map(toMs));\n}\n\nfunction toMs(value: string): number {\n const amount = Number.parseFloat(value);\n\n if (Number.isNaN(amount)) {\n return 0;\n }\n\n return value.trim().endsWith('ms') ? amount : amount * 1000;\n}\n","import { DestroyRef, ElementRef, type OutputEmitterRef, type Signal, afterRenderEffect, inject } from '@angular/core';\n\nimport { afterExit } from './dialog-exit';\n\ntype SharedReason = 'escape' | 'backdrop' | 'cross' | 'programmatic';\n\n/** @internal */\nexport type ModalCloseConfig<R extends string> = {\n readonly open: Signal<boolean>;\n readonly busy: Signal<boolean>;\n readonly dismissed: OutputEmitterRef<void>;\n readonly closed: OutputEmitterRef<R | SharedReason>;\n readonly reset?: () => void;\n readonly opening?: () => void;\n};\n\n/**\n * The close protocol of a modal on the native <dialog> under the host: `open` drives `showModal()` and `close()`,\n * Escape and a press-and-release on the veil close it unless `busy`, `dismissed` reports a close the user asked for\n * and `closed` its reason once the exit transition has played. `opening` runs just before `showModal()`. Must be\n * created in an injection context.\n *\n * @internal Shared by `ui-dialog` and `ui-drawer`, not meant for applications.\n */\nexport class ModalClose<R extends string> {\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #config: ModalCloseConfig<R>;\n\n #pressedOnBackdrop = false;\n #reason: R | SharedReason | null = null;\n #cancelExit: () => void = () => undefined;\n\n constructor(config: ModalCloseConfig<R>) {\n this.#config = config;\n inject(DestroyRef).onDestroy(() => this.#cancelExit());\n\n afterRenderEffect(() => {\n const dialog = this.#dialog;\n\n if (config.open() && !dialog.open) {\n this.#cancelExit();\n config.reset?.();\n config.opening?.();\n dialog.showModal();\n } else if (!config.open() && dialog.open) {\n this.close('programmatic');\n }\n });\n }\n\n close(reason: R | SharedReason): void {\n if (this.#dialog.open) {\n this.#reason = reason;\n this.#dialog.close();\n }\n }\n\n onCancel(event: Event): void {\n if (event.target !== event.currentTarget) {\n return;\n }\n event.preventDefault();\n if (!this.#config.busy()) {\n this.close('escape');\n }\n }\n\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape' && this.#config.busy() && (event.target as Element).closest('dialog') === this.#dialog) {\n event.preventDefault();\n }\n }\n\n onPointerDown(event: MouseEvent): void {\n this.#pressedOnBackdrop = event.target === this.#dialog && this.#outside(event);\n }\n\n onClick(event: MouseEvent): void {\n if (this.#pressedOnBackdrop && !this.#config.busy() && event.target === this.#dialog && this.#outside(event)) {\n this.close('backdrop');\n }\n this.#pressedOnBackdrop = false;\n }\n\n onNativeClose(): void {\n const asked = this.#reason;\n\n this.#reason = null;\n if (this.#dialog.open) {\n return;\n }\n if (asked === null && this.#config.busy()) {\n this.#dialog.showModal();\n return;\n }\n const reason = asked ?? 'escape';\n if (reason !== 'programmatic') {\n this.#config.dismissed.emit();\n }\n this.#cancelExit();\n this.#cancelExit = afterExit(this.#dialog, () => {\n this.#cancelExit = () => undefined;\n this.#config.reset?.();\n this.#config.closed.emit(reason);\n });\n }\n\n get #dialog(): HTMLDialogElement {\n return this.#host.nativeElement.querySelector('dialog') as HTMLDialogElement;\n }\n\n #outside(event: MouseEvent): boolean {\n const rect = this.#dialog.getBoundingClientRect();\n\n return (\n event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom\n );\n }\n}\n","const DISMISS_RATIO = 0.3;\nconst DISMISS_SPEED = 0.5;\nconst SPEED_WINDOW = 100;\nconst SLOP = 6;\nconst CONTROLS = 'button, a, input, select, textarea, [role=\"button\"]';\n\ntype Sample = { y: number; at: number };\n\ntype Gesture = {\n id: number;\n startX: number;\n startY: number;\n dragging: boolean;\n height: number;\n offset: number;\n samples: Sample[];\n};\n\nexport class SheetDrag {\n readonly #panel: HTMLElement;\n readonly #grips: readonly HTMLElement[];\n readonly #dismiss: () => void;\n readonly #enabled: () => boolean;\n #gesture: Gesture | null = null;\n\n constructor(panel: HTMLElement, grips: readonly HTMLElement[], dismiss: () => void, enabled: () => boolean) {\n this.#panel = panel;\n this.#grips = grips;\n this.#dismiss = dismiss;\n this.#enabled = enabled;\n\n for (const grip of grips) {\n grip.addEventListener('pointerdown', this.#onDown);\n grip.addEventListener('pointermove', this.#onMove);\n grip.addEventListener('pointerup', this.#onUp);\n grip.addEventListener('pointercancel', this.#onCancel);\n }\n }\n\n reset(): void {\n this.#gesture = null;\n this.#panel.removeAttribute('data-dragging');\n this.#panel.style.removeProperty('--drag-y');\n }\n\n destroy(): void {\n for (const grip of this.#grips) {\n grip.removeEventListener('pointerdown', this.#onDown);\n grip.removeEventListener('pointermove', this.#onMove);\n grip.removeEventListener('pointerup', this.#onUp);\n grip.removeEventListener('pointercancel', this.#onCancel);\n }\n }\n\n readonly #onDown = (event: PointerEvent): void => {\n const grip = event.currentTarget as HTMLElement;\n\n if (event.button !== 0 || !this.#enabled() || !isSheet() || (event.target as Element).closest(CONTROLS)) {\n return;\n }\n\n grip.setPointerCapture(event.pointerId);\n this.#gesture = {\n id: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n dragging: false,\n height: 0,\n offset: 0,\n samples: [{ y: event.clientY, at: event.timeStamp }],\n };\n };\n\n readonly #onMove = (event: PointerEvent): void => {\n const gesture = this.#current(event);\n\n if (!gesture) {\n return;\n }\n\n const dx = event.clientX - gesture.startX;\n const dy = event.clientY - gesture.startY;\n\n if (!gesture.dragging) {\n if (Math.max(Math.abs(dx), Math.abs(dy)) < SLOP) {\n return;\n }\n if (Math.abs(dx) > Math.abs(dy)) {\n this.#gesture = null;\n return;\n }\n gesture.dragging = true;\n gesture.height = this.#panel.getBoundingClientRect().height;\n this.#panel.setAttribute('data-dragging', '');\n }\n\n gesture.offset = Math.max(0, dy);\n gesture.samples.push({ y: event.clientY, at: event.timeStamp });\n this.#panel.style.setProperty('--drag-y', `${gesture.offset}px`);\n };\n\n readonly #onUp = (event: PointerEvent): void => {\n const gesture = this.#current(event);\n\n if (!gesture) {\n return;\n }\n\n this.#gesture = null;\n\n if (!gesture.dragging) {\n return;\n }\n\n this.#panel.removeAttribute('data-dragging');\n\n const release = { y: event.clientY, at: event.timeStamp };\n\n if (gesture.offset > gesture.height * DISMISS_RATIO || releaseSpeed(gesture.samples, release) > DISMISS_SPEED) {\n this.#dismiss();\n } else {\n this.reset();\n }\n };\n\n readonly #onCancel = (event: PointerEvent): void => {\n if (this.#current(event)) {\n this.#gesture = null;\n this.#panel.removeAttribute('data-dragging');\n this.reset();\n }\n };\n\n #current(event: PointerEvent): Gesture | null {\n return this.#gesture?.id === event.pointerId ? this.#gesture : null;\n }\n}\n\nfunction isSheet(): boolean {\n return typeof matchMedia === 'function' && !matchMedia('(min-width: 64rem)').matches;\n}\n\nfunction releaseSpeed(samples: readonly Sample[], last: Sample): number {\n const first = samples.find((sample) => sample.at >= last.at - SPEED_WINDOW) ?? last;\n const elapsed = last.at - first.at;\n\n return elapsed > 0 ? (last.y - first.y) / elapsed : 0;\n}\n","import {\n Component,\n DestroyRef,\n ElementRef,\n afterNextRender,\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { DIALOG_STYLES } from './internal/dialog-styles';\nimport { ModalClose } from './internal/modal-close';\nimport { SheetDrag } from './internal/sheet-drag';\n\n/** Named dialog widths; any other CSS length is accepted as is. */\nexport const DIALOG_WIDTHS = ['md', 'lg'] as const;\nexport type DialogWidth = (typeof DIALOG_WIDTHS)[number];\n\nconst WIDTH_VALUES: Record<DialogWidth, string> = {\n md: '28rem',\n lg: '560px',\n};\n\n/** `confirm` is a short alertdialog: no cross, no hairlines, one 24px padding, 440px wide unless told otherwise. */\nexport const DIALOG_VARIANTS = ['default', 'confirm'] as const;\nexport type DialogVariant = (typeof DIALOG_VARIANTS)[number];\n\n/** `full` makes the sheet under `64rem` fill the screen below the status area; `fit` sizes it to its content. */\nexport const DIALOG_SHEETS = ['fit', 'full'] as const;\nexport type DialogSheet = (typeof DIALOG_SHEETS)[number];\n\ntype VariantClasses = {\n handle: string;\n header: string;\n body: string;\n footer: string;\n};\n\nconst VARIANTS: Record<DialogVariant, VariantClasses> = {\n default: {\n handle: 'pt-[7.5px]',\n header: 'pb-3 lg:py-4 lg:pl-6',\n body: 'py-4 lg:py-5',\n footer: 'pt-3 empty:hidden lg:py-4',\n },\n confirm: {\n handle: 'pt-[11.5px]',\n header: 'pt-3 lg:pt-6 lg:pl-6',\n body: 'pt-3',\n footer: 'not-empty:pt-5 lg:pb-6 lg:not-empty:pt-6',\n },\n};\n\nconst DEFAULT_WIDTHS: Record<DialogVariant, string> = {\n default: 'lg',\n confirm: '440px',\n};\n\n/** What started a close, as `closed` reports it. */\nexport const DIALOG_CLOSE_REASONS = ['escape', 'backdrop', 'cross', 'drag', 'programmatic'] as const;\nexport type DialogCloseReason = (typeof DIALOG_CLOSE_REASONS)[number];\n\nconst nextId = (() => {\n let count = 0;\n\n return () => `ui-dialog-${++count}`;\n})();\n\n/**\n * Modal dialog on the native <dialog>: a bottom sheet under `64rem`, centered above it.\n *\n * `busy` keeps it open while its action runs: Escape, a backdrop click and a sheet drag do nothing\n * and the cross is disabled. The owner disables its own buttons and still closes it through `open`.\n *\n * @example\n * <ui-dialog heading=\"Buy\" description=\"Ferrari\" closeLabel=\"Close\" width=\"528px\" [open]=\"buying()\" (dismissed)=\"buying.set(false)\">\n * <p>Body</p>\n * <button dialogActions ui-button variant=\"outline\" class=\"max-lg:hidden\" (click)=\"buying.set(false)\">Cancel</button>\n * <button dialogActions ui-button>Buy 40 shares</button>\n * </ui-dialog>\n */\n@Component({\n selector: 'ui-dialog',\n host: {\n '(pointerdown)': 'modal.onPointerDown($event)',\n '(click)': 'modal.onClick($event)',\n '(keydown)': 'modal.onKeydown($event)',\n },\n template: `\n <dialog\n #dlg\n [attr.aria-busy]=\"busy() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-labelledby]=\"headingId\"\n [attr.role]=\"variant() === 'confirm' ? 'alertdialog' : 'dialog'\"\n [class]=\"classes()\"\n [style.--dialog-width]=\"widthValue()\"\n (cancel)=\"modal.onCancel($event)\"\n (close)=\"modal.onNativeClose()\"\n >\n <div\n aria-hidden=\"true\"\n class=\"flex h-5 touch-none justify-center lg:hidden\"\n data-dialog-handle\n [class]=\"spec().handle\"\n >\n <span class=\"rounded-pill h-[5px] w-9 bg-(--border)\"></span>\n </div>\n\n <div data-dialog-header [class]=\"headerClasses()\">\n <div class=\"flex min-w-0 flex-1 flex-col\" [class.max-lg:pt-1]=\"description()\">\n <h2 class=\"text-title font-semibold\" [id]=\"headingId\">{{ heading() }}</h2>\n\n @if (description()) {\n <p\n class=\"text-label text-(--muted-foreground)\"\n [class.truncate]=\"truncateDescription()\"\n [id]=\"descriptionId\"\n >\n {{ description() }}\n </p>\n }\n </div>\n\n @if (closeLabel()) {\n <button\n type=\"button\"\n [attr.aria-label]=\"closeLabel()\"\n [class]=\"crossClasses\"\n [disabled]=\"busy()\"\n (click)=\"modal.close('cross')\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"block size-[22px] fill-none stroke-current stroke-[1.75]\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n }\n </div>\n\n <div\n class=\"min-h-0 flex-1 overflow-y-auto px-4 outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) lg:px-6\"\n data-dialog-body\n [attr.aria-labelledby]=\"scrollable() ? headingId : null\"\n [attr.role]=\"scrollable() ? 'region' : null\"\n [attr.tabindex]=\"scrollable() ? 0 : null\"\n [id]=\"bodyId\"\n >\n <div class=\"flex flex-col gap-4 empty:hidden\" [class]=\"spec().body\">\n <ng-content />\n </div>\n </div>\n\n <div data-dialog-footer [class]=\"footerClasses()\">\n <ng-content select=\"[dialogActions]\" />\n </div>\n </dialog>\n `,\n styles: DIALOG_STYLES,\n})\nexport class UiDialog {\n readonly heading = input.required<string>();\n readonly description = input<string>();\n readonly closeLabel = input<string>();\n readonly variant = input<DialogVariant>('default');\n readonly sheet = input<DialogSheet>('fit');\n readonly truncateDescription = input(false, { transform: booleanAttribute });\n readonly width = input<DialogWidth | (string & {})>();\n readonly open = input(false, { transform: booleanAttribute });\n readonly busy = input(false, { transform: booleanAttribute });\n readonly dismissed = output<void>();\n readonly closed = output<DialogCloseReason>();\n\n protected readonly headingId = nextId();\n protected readonly descriptionId = `${this.headingId}-description`;\n protected readonly bodyId = `${this.headingId}-body`;\n protected readonly scrollable = signal(false);\n protected readonly stacked = signal(false);\n\n protected readonly describedBy = computed(() => {\n if (this.description()) {\n return this.descriptionId;\n }\n\n return this.variant() === 'confirm' ? this.bodyId : null;\n });\n\n protected readonly widthValue = computed(() => {\n const width = this.width() ?? DEFAULT_WIDTHS[this.variant()];\n\n return Object.hasOwn(WIDTH_VALUES, width) ? WIDTH_VALUES[width as DialogWidth] : width;\n });\n\n protected readonly spec = computed(() => VARIANTS[this.variant()]);\n\n protected readonly hairlines = computed(() => Boolean(this.closeLabel()) && this.variant() === 'default');\n\n protected readonly headerClasses = computed(\n () =>\n `flex ${this.description() ? 'items-start' : 'items-center'} gap-2 pl-4 max-lg:touch-none lg:gap-3 ${this.spec().header} ${this.closeLabel() ? 'pr-2 lg:pr-4' : 'pr-4 lg:pr-6'} ${this.hairlines() ? 'shadow-[inset_0_-1px_0_var(--hairline)]' : ''}`,\n );\n\n protected readonly crossClasses =\n 'rounded-pill lg:rounded-control grid size-11 flex-none cursor-pointer place-items-center text-(--muted-foreground) transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out outline-none focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-(--ring) active:scale-(--press-scale) active:bg-(--soft) disabled:pointer-events-none disabled:opacity-40 lg:size-9 lg:hover:bg-(--glow) lg:hover:text-(--foreground)';\n\n protected readonly footerClasses = computed(\n () =>\n `max-lg:[&>[ui-button]]:text-body flex justify-end gap-2 px-4 pb-[calc(8px+env(safe-area-inset-bottom))] max-lg:flex-col-reverse max-lg:[&>[ui-button]]:h-[50px] max-lg:[&>[ui-button]]:w-full lg:px-6 ${this.spec().footer} ${this.hairlines() ? 'shadow-[inset_0_1px_0_var(--hairline)]' : ''}`,\n );\n\n protected readonly classes = computed(\n () =>\n `open:flex w-full flex-col overflow-hidden m-auto mt-auto max-lg:max-h-[calc(100dvh-2rem)] lg:max-h-[calc(100dvh-96px)] max-lg:mb-0 max-lg:max-w-none max-lg:rounded-b-none lg:max-w-(--dialog-width) rounded-container bg-(--card) text-(--foreground) outline-none shadow-[0_0_0_1px_var(--border),0_24px_64px_rgb(0_0_0/0.24)] max-lg:shadow-[0_-1px_0_var(--border),0_-12px_32px_rgb(0_0_0/0.16)] ${this.stacked() ? 'backdrop:bg-black/[0.24]' : 'backdrop:bg-black/[0.36]'} ${this.sheet() === 'full' ? 'max-lg:h-[calc(100dvh-58px)]' : ''}`,\n );\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n #drag: SheetDrag | null = null;\n\n protected readonly modal: ModalClose<DialogCloseReason>;\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n\n afterNextRender(() => {\n const host = this.#host.nativeElement;\n const dialog = host.querySelector('dialog') as HTMLDialogElement;\n const grips = ['[data-dialog-handle]', '[data-dialog-header]'].map(\n (grip) => host.querySelector(grip) as HTMLElement,\n );\n\n this.#drag = new SheetDrag(\n dialog,\n grips,\n () => this.modal.close('drag'),\n () => !this.busy(),\n );\n destroyRef.onDestroy(() => this.#drag?.destroy());\n\n if (typeof ResizeObserver === 'undefined') {\n return;\n }\n\n const body = host.querySelector('[data-dialog-body]') as HTMLElement;\n const observer = new ResizeObserver(() => this.scrollable.set(body.scrollHeight > body.clientHeight));\n\n observer.observe(body);\n observer.observe(body.firstElementChild as Element);\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n this.modal = new ModalClose<DialogCloseReason>({\n open: this.open,\n busy: this.busy,\n dismissed: this.dismissed,\n closed: this.closed,\n reset: () => this.#drag?.reset(),\n opening: () => this.stacked.set(this.#overAnotherModal()),\n });\n }\n\n #overAnotherModal(): boolean {\n const open = this.#host.nativeElement.ownerDocument.querySelectorAll('dialog[open]');\n\n return Array.from(open).some((dialog) => dialog.matches(':modal'));\n }\n}\n"],"mappings":";;ACAA,MAAM,QAAQ;AAEd,SAAgB,UAAU,SAAsB,MAAgB;CAC9D,MAAM,QAAQ,iBAAiB,OAAO;CACtC,MAAM,OAAO,QAAQ,MAAM,kBAAkB,IAAI,QAAQ,MAAM,eAAe;CAE9E,IAAI,SAAS,GAAG;EACd,KAAI;EACJ,aAAa;CACf;CAEA,MAAM,SAAS,UAAgC;EAC7C,IAAI,MAAM,WAAW,WAAW,CAAC,MAAM,eAAe;GACpD,OAAM;GACN,KAAI;EACN;CACF;CACA,MAAM,QAAQ,iBAAgB;EAC5B,OAAM;EACN,KAAI;CACN,GAAG,OAAO,KAAK;CACf,MAAM,eAAoB;EACxB,aAAa,KAAK;EAClB,QAAQ,oBAAoB,iBAAiB,KAAK;CACpD;CAEA,QAAQ,iBAAiB,iBAAiB,KAAK;CAE/C,OAAO;AACT;AAEA,SAAS,QAAQ,MAAY;CAC3B,OAAO,KAAK,IAAI,GAAG,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;AACjD;AAEA,SAAS,KAAK,OAAa;CACzB,MAAM,SAAS,OAAO,WAAW,KAAK;CAEtC,IAAI,OAAO,MAAM,MAAM,GACrB,OAAO;CAGT,OAAO,MAAM,KAAI,CAAE,CAAC,SAAS,IAAI,IAAI,SAAS,SAAS;AACzD;ACnBA,IAAa,aAAb,MAAuB;CACZ,QAAQ,OAAgC,UAAU;CAClD;CAET,qBAAqB;CACrB,UAAmC;CACnC,oBAAgC;CAEhC,YAAY,QAA2B;EACrC,KAAK,UAAU;EACf,OAAO,UAAU,CAAC,CAAC,gBAAgB,KAAK,YAAW,CAAE;EAErD,wBAAuB;GACrB,MAAM,SAAS,KAAK;GAEpB,IAAI,OAAO,KAAI,KAAM,CAAC,OAAO,MAAM;IACjC,KAAK,YAAW;IAChB,OAAO,QAAO;IACd,OAAO,UAAS;IAChB,OAAO,UAAS;GAClB,OAAO,IAAI,CAAC,OAAO,KAAI,KAAM,OAAO,MAClC,KAAK,MAAM,cAAc;EAE7B,CAAC;CACH;CAEA,MAAM,QAAwB;EAC5B,IAAI,KAAK,QAAQ,MAAM;GACrB,KAAK,UAAU;GACf,KAAK,QAAQ,MAAK;EACpB;CACF;CAEA,SAAS,OAAY;EACnB,IAAI,MAAM,WAAW,MAAM,eACzB;EAEF,MAAM,eAAc;EACpB,IAAI,CAAC,KAAK,QAAQ,KAAI,GACpB,KAAK,MAAM,QAAQ;CAEvB;CAEA,UAAU,OAAoB;EAC5B,IAAI,MAAM,QAAQ,YAAY,KAAK,QAAQ,KAAI,KAAO,MAAM,OAAmB,QAAQ,QAAQ,MAAM,KAAK,SACxG,MAAM,eAAc;CAExB;CAEA,cAAc,OAAiB;EAC7B,KAAK,qBAAqB,MAAM,WAAW,KAAK,WAAW,KAAK,SAAS,KAAK;CAChF;CAEA,QAAQ,OAAiB;EACvB,IAAI,KAAK,sBAAsB,CAAC,KAAK,QAAQ,KAAI,KAAM,MAAM,WAAW,KAAK,WAAW,KAAK,SAAS,KAAK,GACzG,KAAK,MAAM,UAAU;EAEvB,KAAK,qBAAqB;CAC5B;CAEA,gBAAa;EACX,MAAM,QAAQ,KAAK;EAEnB,KAAK,UAAU;EACf,IAAI,KAAK,QAAQ,MACf;EAEF,IAAI,UAAU,QAAQ,KAAK,QAAQ,KAAI,GAAI;GACzC,KAAK,QAAQ,UAAS;GACtB;EACF;EACA,MAAM,SAAS,SAAS;EACxB,IAAI,WAAW,gBACb,KAAK,QAAQ,UAAU,KAAI;EAE7B,KAAK,YAAW;EAChB,KAAK,cAAc,UAAU,KAAK,eAAc;GAC9C,KAAK,oBAAoB;GACzB,KAAK,QAAQ,QAAO;GACpB,KAAK,QAAQ,OAAO,KAAK,MAAM;EACjC,CAAC;CACH;CAEA,IAAI,UAAO;EACT,OAAO,KAAK,MAAM,cAAc,cAAc,QAAQ;CACxD;CAEA,SAAS,OAAiB;EACxB,MAAM,OAAO,KAAK,QAAQ,sBAAqB;EAE/C,OACE,MAAM,UAAU,KAAK,QAAQ,MAAM,UAAU,KAAK,SAAS,MAAM,UAAU,KAAK,OAAO,MAAM,UAAU,KAAK;CAEhH;AACD;ACtHD,MAAM,gBAAgB;AACtB,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,OAAO;AACb,MAAM,WAAW;AAcjB,IAAa,YAAb,MAAsB;CACX;CACA;CACA;CACA;CACT,WAA2B;CAE3B,YAAY,OAAoB,OAA+B,SAAqB,SAAsB;EACxG,KAAK,SAAS;EACd,KAAK,SAAS;EACd,KAAK,WAAW;EAChB,KAAK,WAAW;EAEhB,KAAK,MAAM,QAAQ,OAAO;GACxB,KAAK,iBAAiB,eAAe,KAAK,OAAO;GACjD,KAAK,iBAAiB,eAAe,KAAK,OAAO;GACjD,KAAK,iBAAiB,aAAa,KAAK,KAAK;GAC7C,KAAK,iBAAiB,iBAAiB,KAAK,SAAS;EACvD;CACF;CAEA,QAAK;EACH,KAAK,WAAW;EAChB,KAAK,OAAO,gBAAgB,eAAe;EAC3C,KAAK,OAAO,MAAM,eAAe,UAAU;CAC7C;CAEA,UAAO;EACL,KAAK,MAAM,QAAQ,KAAK,QAAQ;GAC9B,KAAK,oBAAoB,eAAe,KAAK,OAAO;GACpD,KAAK,oBAAoB,eAAe,KAAK,OAAO;GACpD,KAAK,oBAAoB,aAAa,KAAK,KAAK;GAChD,KAAK,oBAAoB,iBAAiB,KAAK,SAAS;EAC1D;CACF;CAES,WAAW,UAA6B;EAC/C,MAAM,OAAO,MAAM;EAEnB,IAAI,MAAM,WAAW,KAAK,CAAC,KAAK,SAAQ,KAAM,CAAC,QAAO,KAAO,MAAM,OAAmB,QAAQ,QAAQ,GACpG;EAGF,KAAK,kBAAkB,MAAM,SAAS;EACtC,KAAK,WAAW;GACd,IAAI,MAAM;GACV,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,UAAU;GACV,QAAQ;GACR,QAAQ;GACR,SAAS,CAAC;IAAE,GAAG,MAAM;IAAS,IAAI,MAAM;GAAS,CAAE;EACpD;CACH;CAES,WAAW,UAA6B;EAC/C,MAAM,UAAU,KAAK,SAAS,KAAK;EAEnC,IAAI,CAAC,SACH;EAGF,MAAM,KAAK,MAAM,UAAU,QAAQ;EACnC,MAAM,KAAK,MAAM,UAAU,QAAQ;EAEnC,IAAI,CAAC,QAAQ,UAAU;GACrB,IAAI,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC,IAAI,MACzC;GAEF,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,GAAG;IAC/B,KAAK,WAAW;IAChB;GACF;GACA,QAAQ,WAAW;GACnB,QAAQ,SAAS,KAAK,OAAO,sBAAqB,CAAE,CAAC;GACrD,KAAK,OAAO,aAAa,iBAAiB,EAAE;EAC9C;EAEA,QAAQ,SAAS,KAAK,IAAI,GAAG,EAAE;EAC/B,QAAQ,QAAQ,KAAK;GAAE,GAAG,MAAM;GAAS,IAAI,MAAM;EAAS,CAAE;EAC9D,KAAK,OAAO,MAAM,YAAY,YAAY,GAAG,QAAQ,OAAM,GAAI;CACjE;CAES,SAAS,UAA6B;EAC7C,MAAM,UAAU,KAAK,SAAS,KAAK;EAEnC,IAAI,CAAC,SACH;EAGF,KAAK,WAAW;EAEhB,IAAI,CAAC,QAAQ,UACX;EAGF,KAAK,OAAO,gBAAgB,eAAe;EAE3C,MAAM,UAAU;GAAE,GAAG,MAAM;GAAS,IAAI,MAAM;EAAS;EAEvD,IAAI,QAAQ,SAAS,QAAQ,SAAS,iBAAiB,aAAa,QAAQ,SAAS,OAAO,IAAI,eAC9F,KAAK,SAAQ;OAEb,KAAK,MAAK;CAEd;CAES,aAAa,UAA6B;EACjD,IAAI,KAAK,SAAS,KAAK,GAAG;GACxB,KAAK,WAAW;GAChB,KAAK,OAAO,gBAAgB,eAAe;GAC3C,KAAK,MAAK;EACZ;CACF;CAEA,SAAS,OAAmB;EAC1B,OAAO,KAAK,UAAU,OAAO,MAAM,YAAY,KAAK,WAAW;CACjE;AACD;AAED,SAAS,UAAO;CACd,OAAO,OAAO,eAAe,cAAc,CAAC,WAAW,oBAAoB,CAAC,CAAC;AAC/E;AAEA,SAAS,aAAa,SAA4B,MAAY;CAC5D,MAAM,QAAQ,QAAQ,MAAM,WAAW,OAAO,MAAM,KAAK,KAAK,YAAY,KAAK;CAC/E,MAAM,UAAU,KAAK,KAAK,MAAM;CAEhC,OAAO,UAAU,KAAK,KAAK,IAAI,MAAM,KAAK,UAAU;AACtD;ACjIA,MAAa,gBAAgB,CAAC,MAAM,IAAI;AAGxC,MAAM,eAA4C;CAChD,IAAI;CACJ,IAAI;AACL;AAGD,MAAa,kBAAkB,CAAC,WAAW,SAAS;AAIpD,MAAa,gBAAgB,CAAC,OAAO,MAAM;AAU3C,MAAM,WAAkD;CACtD,SAAS;EACP,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,QAAQ;CACT;CACD,SAAS;EACP,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,QAAQ;CACT;AACF;AAED,MAAM,iBAAgD;CACpD,SAAS;CACT,SAAS;AACV;AAGD,MAAa,uBAAuB;CAAC;CAAU;CAAY;CAAS;CAAQ;AAAc;AAG1F,MAAM,gBAAe;CACnB,IAAI,QAAQ;CAEZ,aAAa,aAAa,EAAE;AAC9B,EAAA,CAAE;AAoGF,IAAa,WAAb,MAAa,SAAQ;CACV,UAAU,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAClC,cAAc,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAC7B,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,UAAU,MAAqB,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACzC,QAAQ,MAAmB,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACjC,sBAAsB,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,sBAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CAChE,QAAQ,MAAoC,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC5C,OAAO,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,OAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CACjD,OAAO,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,OAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CACjD,YAAY,OAAM;CAClB,SAAS,OAAM;CAEL,YAAY,OAAM;CAClB,gBAAgB,GAAG,KAAK,UAAS;CACjC,SAAS,GAAG,KAAK,UAAS;CAC1B,aAAa,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC1B,UAAU,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEvB,cAAc,eAAc;EAC7C,IAAI,KAAK,YAAW,GAClB,OAAO,KAAK;EAGd,OAAO,KAAK,QAAO,MAAO,YAAY,KAAK,SAAS;CACtD,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAEiB,aAAa,eAAc;EAC5C,MAAM,QAAQ,KAAK,MAAK,KAAM,eAAe,KAAK,QAAO;EAEzD,OAAO,OAAO,OAAO,cAAc,KAAK,IAAI,aAAa,SAAwB;CACnF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAEiB,OAAO,eAAe,SAAS,KAAK,QAAO,IAAI,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAE/C,YAAY,eAAe,QAAQ,KAAK,WAAU,CAAE,KAAK,KAAK,QAAO,MAAO,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAEtF,gBAAgB,eAE/B,QAAQ,KAAK,YAAW,IAAK,gBAAgB,eAAc,yCAA0C,KAAK,KAAI,CAAE,CAAC,OAAM,GAAI,KAAK,WAAU,IAAK,iBAAiB,eAAc,GAAI,KAAK,UAAS,IAAK,4CAA4C,MACpP,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAEkB,eACjB;CAEiB,gBAAgB,eAE/B,yMAAyM,KAAK,KAAI,CAAE,CAAC,OAAM,GAAI,KAAK,UAAS,IAAK,2CAA2C,MAChS,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAEkB,UAAU,eAEzB,wYAAwY,KAAK,QAAO,IAAK,6BAA6B,2BAA0B,GAAI,KAAK,MAAK,MAAO,SAAS,iCAAiC,MAClhB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,QAAQ,OAAgC,UAAU;CAE3D,QAA0B;CAEP;CAEnB,cAAA;EACE,MAAM,aAAa,OAAO,UAAU;EAEpC,sBAAqB;GACnB,MAAM,OAAO,KAAK,MAAM;GACxB,MAAM,SAAS,KAAK,cAAc,QAAQ;GAC1C,MAAM,QAAQ,CAAC,wBAAwB,sBAAsB,CAAC,CAAC,KAC5D,SAAS,KAAK,cAAc,IAAI,CAAgB;GAGnD,KAAK,QAAQ,IAAI,UACf,QACA,aACM,KAAK,MAAM,MAAM,MAAM,SACvB,CAAC,KAAK,KAAI,CAAE;GAEpB,WAAW,gBAAgB,KAAK,OAAO,QAAO,CAAE;GAEhD,IAAI,OAAO,mBAAmB,aAC5B;GAGF,MAAM,OAAO,KAAK,cAAc,oBAAoB;GACpD,MAAM,WAAW,IAAI,qBAAqB,KAAK,WAAW,IAAI,KAAK,eAAe,KAAK,YAAY,CAAC;GAEpG,SAAS,QAAQ,IAAI;GACrB,SAAS,QAAQ,KAAK,iBAA4B;GAClD,WAAW,gBAAgB,SAAS,WAAU,CAAE;EAClD,CAAC;EAED,KAAK,QAAQ,IAAI,WAA8B;GAC7C,MAAM,KAAK;GACX,MAAM,KAAK;GACX,WAAW,KAAK;GAChB,QAAQ,KAAK;GACb,aAAa,KAAK,OAAO,MAAK;GAC9B,eAAe,KAAK,QAAQ,IAAI,KAAK,kBAAiB,CAAE;EACzD,CAAA;CACH;CAEA,oBAAiB;EACf,MAAM,OAAO,KAAK,MAAM,cAAc,cAAc,iBAAiB,cAAc;EAEnF,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,WAAW,OAAO,QAAQ,QAAQ,CAAC;CACnE;CAzGW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAQ,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAR,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAQ,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,qBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA;GAAA,WAAA;GAAA,QAAA;EAAA;EAAA,MAAA,EAAA,WAAA;GAAA,eAAA;GAAA,SAAA;GAAA,WAAA;EAAA,EAAA;EAAA,UAAA;EAAA,UA9ET;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2ET,UAAA;EAAA,QAAA,CAAA,o3CAAA;CAAA,CAAA;;AAGU,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAQ,YAAA,CAAA;EArFpB,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAW,MACf;IACJ,iBAAiB;IACjB,WAAW;IACX,aAAa;GACd;GAAA,UACS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2ET,QAAA,CAAA,o3CAAA;EAAA,CAAA"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-dialog.mjs","names":[],"sources":["../../../projects/ui/dialog/internal/dialog-styles.ts","../../../projects/ui/dialog/internal/dialog-exit.ts","../../../projects/ui/dialog/internal/modal-close.ts","../../../projects/ui/dialog/internal/sheet-drag.ts","../../../projects/ui/dialog/dialog.ts"],"sourcesContent":["export const DIALOG_STYLES = `\ndialog {\n --dialog-ease: var(--ease-sheet);\n transition:\n transform var(--duration-base) var(--dialog-ease),\n overlay var(--duration-base) allow-discrete,\n display var(--duration-base) allow-discrete;\n transform: translateY(var(--drag-y, 0px));\n}\n\ndialog:not([open]) {\n transform: translateY(100%);\n transition-duration: var(--duration-exit);\n}\n\n@starting-style {\n dialog[open] {\n transform: translateY(100%);\n }\n}\n\ndialog[data-dragging] {\n transition: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n dialog {\n transition:\n opacity var(--duration-base) var(--dialog-ease),\n overlay var(--duration-base) allow-discrete,\n display var(--duration-base) allow-discrete;\n opacity: 1;\n }\n\n dialog:not([open]) {\n opacity: 0;\n transform: translateY(var(--drag-y, 0px));\n }\n\n @starting-style {\n dialog[open] {\n opacity: 0;\n transform: translateY(0);\n }\n }\n}\n\n@media (min-width: 64rem) {\n dialog {\n --dialog-ease: var(--ease-out);\n transition:\n opacity var(--duration-base) var(--dialog-ease),\n transform var(--duration-base) var(--dialog-ease),\n overlay var(--duration-base) allow-discrete,\n display var(--duration-base) allow-discrete;\n opacity: 1;\n transform: scale(1);\n }\n\n dialog:not([open]) {\n opacity: 0;\n transform: scale(var(--enter-scale));\n }\n\n @starting-style {\n dialog[open] {\n opacity: 0;\n transform: scale(var(--enter-scale));\n }\n }\n}\n\ndialog::backdrop {\n transition: opacity var(--duration-base) var(--ease-out);\n opacity: 1;\n}\n\ndialog:not([open])::backdrop {\n opacity: 0;\n transition-duration: var(--duration-exit);\n}\n\n@starting-style {\n dialog[open]::backdrop {\n opacity: 0;\n }\n}\n`;\n","const GRACE = 50;\n\nexport function afterExit(element: HTMLElement, done: () => void): () => void {\n const style = getComputedStyle(element);\n const wait = longest(style.transitionDuration) + longest(style.transitionDelay);\n\n if (wait === 0) {\n done();\n return () => undefined;\n }\n\n const onEnd = (event: TransitionEvent): void => {\n if (event.target === element && !event.pseudoElement) {\n cancel();\n done();\n }\n };\n const timer = setTimeout(() => {\n cancel();\n done();\n }, wait + GRACE);\n const cancel = (): void => {\n clearTimeout(timer);\n element.removeEventListener('transitionend', onEnd);\n };\n\n element.addEventListener('transitionend', onEnd);\n\n return cancel;\n}\n\nfunction longest(list: string): number {\n return Math.max(0, ...list.split(',').map(toMs));\n}\n\nfunction toMs(value: string): number {\n const amount = Number.parseFloat(value);\n\n if (Number.isNaN(amount)) {\n return 0;\n }\n\n return value.trim().endsWith('ms') ? amount : amount * 1000;\n}\n","import { DestroyRef, ElementRef, type OutputEmitterRef, type Signal, afterRenderEffect, inject } from '@angular/core';\n\nimport { afterExit } from './dialog-exit';\n\ntype SharedReason = 'escape' | 'backdrop' | 'cross' | 'programmatic';\n\n/** @internal */\nexport type ModalCloseConfig<R extends string> = {\n readonly open: Signal<boolean>;\n readonly busy: Signal<boolean>;\n readonly dismissed: OutputEmitterRef<void>;\n readonly closed: OutputEmitterRef<R | SharedReason>;\n readonly reset?: () => void;\n readonly opening?: () => void;\n};\n\n/**\n * The close protocol of a modal on the native <dialog> under the host: `open` drives `showModal()` and `close()`,\n * Escape and a press-and-release on the veil close it unless `busy`, `dismissed` reports a close the user asked for\n * and `closed` its reason once the exit transition has played. `opening` runs just before `showModal()`. Must be\n * created in an injection context.\n *\n * @internal Shared by `ui-dialog` and `ui-drawer`, not meant for applications.\n */\nexport class ModalClose<R extends string> {\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #config: ModalCloseConfig<R>;\n\n #pressedOnBackdrop = false;\n #reason: R | SharedReason | null = null;\n #cancelExit: () => void = () => undefined;\n\n constructor(config: ModalCloseConfig<R>) {\n this.#config = config;\n inject(DestroyRef).onDestroy(() => this.#cancelExit());\n\n afterRenderEffect(() => {\n const dialog = this.#dialog;\n\n if (config.open() && !dialog.open) {\n this.#cancelExit();\n config.reset?.();\n config.opening?.();\n dialog.showModal();\n } else if (!config.open() && dialog.open) {\n this.close('programmatic');\n }\n });\n }\n\n close(reason: R | SharedReason): void {\n if (this.#dialog.open) {\n this.#reason = reason;\n this.#dialog.close();\n }\n }\n\n onCancel(event: Event): void {\n if (event.target !== event.currentTarget) {\n return;\n }\n event.preventDefault();\n if (!this.#config.busy()) {\n this.close('escape');\n }\n }\n\n onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape' && this.#config.busy() && (event.target as Element).closest('dialog') === this.#dialog) {\n event.preventDefault();\n }\n }\n\n onPointerDown(event: MouseEvent): void {\n this.#pressedOnBackdrop = event.target === this.#dialog && this.#outside(event);\n }\n\n onClick(event: MouseEvent): void {\n if (this.#pressedOnBackdrop && !this.#config.busy() && event.target === this.#dialog && this.#outside(event)) {\n this.close('backdrop');\n }\n this.#pressedOnBackdrop = false;\n }\n\n onNativeClose(): void {\n const asked = this.#reason;\n\n this.#reason = null;\n if (this.#dialog.open) {\n return;\n }\n if (asked === null && this.#config.busy()) {\n this.#dialog.showModal();\n return;\n }\n const reason = asked ?? 'escape';\n if (reason !== 'programmatic') {\n this.#config.dismissed.emit();\n }\n this.#cancelExit();\n this.#cancelExit = afterExit(this.#dialog, () => {\n this.#cancelExit = () => undefined;\n this.#config.reset?.();\n this.#config.closed.emit(reason);\n });\n }\n\n get #dialog(): HTMLDialogElement {\n return this.#host.nativeElement.querySelector('dialog') as HTMLDialogElement;\n }\n\n #outside(event: MouseEvent): boolean {\n const rect = this.#dialog.getBoundingClientRect();\n\n return (\n event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom\n );\n }\n}\n","const DISMISS_RATIO = 0.3;\nconst DISMISS_SPEED = 0.5;\nconst SPEED_WINDOW = 100;\nconst SLOP = 6;\nconst CONTROLS = 'button, a, input, select, textarea, [role=\"button\"]';\n\ntype Sample = { y: number; at: number };\n\ntype Gesture = {\n id: number;\n startX: number;\n startY: number;\n dragging: boolean;\n height: number;\n offset: number;\n samples: Sample[];\n};\n\nexport class SheetDrag {\n readonly #panel: HTMLElement;\n readonly #grips: readonly HTMLElement[];\n readonly #dismiss: () => void;\n readonly #enabled: () => boolean;\n #gesture: Gesture | null = null;\n\n constructor(panel: HTMLElement, grips: readonly HTMLElement[], dismiss: () => void, enabled: () => boolean) {\n this.#panel = panel;\n this.#grips = grips;\n this.#dismiss = dismiss;\n this.#enabled = enabled;\n\n for (const grip of grips) {\n grip.addEventListener('pointerdown', this.#onDown);\n grip.addEventListener('pointermove', this.#onMove);\n grip.addEventListener('pointerup', this.#onUp);\n grip.addEventListener('pointercancel', this.#onCancel);\n }\n }\n\n reset(): void {\n this.#gesture = null;\n this.#panel.removeAttribute('data-dragging');\n this.#panel.style.removeProperty('--drag-y');\n }\n\n destroy(): void {\n for (const grip of this.#grips) {\n grip.removeEventListener('pointerdown', this.#onDown);\n grip.removeEventListener('pointermove', this.#onMove);\n grip.removeEventListener('pointerup', this.#onUp);\n grip.removeEventListener('pointercancel', this.#onCancel);\n }\n }\n\n readonly #onDown = (event: PointerEvent): void => {\n const grip = event.currentTarget as HTMLElement;\n\n if (event.button !== 0 || !this.#enabled() || !isSheet() || (event.target as Element).closest(CONTROLS)) {\n return;\n }\n\n grip.setPointerCapture(event.pointerId);\n this.#gesture = {\n id: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n dragging: false,\n height: 0,\n offset: 0,\n samples: [{ y: event.clientY, at: event.timeStamp }],\n };\n };\n\n readonly #onMove = (event: PointerEvent): void => {\n const gesture = this.#current(event);\n\n if (!gesture) {\n return;\n }\n\n const dx = event.clientX - gesture.startX;\n const dy = event.clientY - gesture.startY;\n\n if (!gesture.dragging) {\n if (Math.max(Math.abs(dx), Math.abs(dy)) < SLOP) {\n return;\n }\n if (Math.abs(dx) > Math.abs(dy)) {\n this.#gesture = null;\n return;\n }\n gesture.dragging = true;\n gesture.height = this.#panel.getBoundingClientRect().height;\n this.#panel.setAttribute('data-dragging', '');\n }\n\n gesture.offset = Math.max(0, dy);\n gesture.samples.push({ y: event.clientY, at: event.timeStamp });\n this.#panel.style.setProperty('--drag-y', `${gesture.offset}px`);\n };\n\n readonly #onUp = (event: PointerEvent): void => {\n const gesture = this.#current(event);\n\n if (!gesture) {\n return;\n }\n\n this.#gesture = null;\n\n if (!gesture.dragging) {\n return;\n }\n\n this.#panel.removeAttribute('data-dragging');\n\n const release = { y: event.clientY, at: event.timeStamp };\n\n if (gesture.offset > gesture.height * DISMISS_RATIO || releaseSpeed(gesture.samples, release) > DISMISS_SPEED) {\n this.#dismiss();\n } else {\n this.reset();\n }\n };\n\n readonly #onCancel = (event: PointerEvent): void => {\n if (this.#current(event)) {\n this.#gesture = null;\n this.#panel.removeAttribute('data-dragging');\n this.reset();\n }\n };\n\n #current(event: PointerEvent): Gesture | null {\n return this.#gesture?.id === event.pointerId ? this.#gesture : null;\n }\n}\n\nfunction isSheet(): boolean {\n return typeof matchMedia === 'function' && !matchMedia('(min-width: 64rem)').matches;\n}\n\nfunction releaseSpeed(samples: readonly Sample[], last: Sample): number {\n const first = samples.find((sample) => sample.at >= last.at - SPEED_WINDOW) ?? last;\n const elapsed = last.at - first.at;\n\n return elapsed > 0 ? (last.y - first.y) / elapsed : 0;\n}\n","import {\n Component,\n DestroyRef,\n ElementRef,\n afterNextRender,\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { DIALOG_STYLES } from './internal/dialog-styles';\nimport { ModalClose } from './internal/modal-close';\nimport { SheetDrag } from './internal/sheet-drag';\n\n/** Named dialog widths; any other CSS length is accepted as is. */\nexport const DIALOG_WIDTHS = ['md', 'lg'] as const;\nexport type DialogWidth = (typeof DIALOG_WIDTHS)[number];\n\nconst WIDTH_VALUES: Record<DialogWidth, string> = {\n md: '28rem',\n lg: '560px',\n};\n\n/** `confirm` is a short alertdialog: no cross, no hairlines, one 24px padding, 440px wide unless told otherwise. */\nexport const DIALOG_VARIANTS = ['default', 'confirm'] as const;\nexport type DialogVariant = (typeof DIALOG_VARIANTS)[number];\n\n/** `full` makes the sheet under `64rem` fill the screen below the status area; `fit` sizes it to its content. */\nexport const DIALOG_SHEETS = ['fit', 'full'] as const;\nexport type DialogSheet = (typeof DIALOG_SHEETS)[number];\n\ntype VariantClasses = {\n handle: string;\n header: string;\n body: string;\n footer: string;\n};\n\nconst VARIANTS: Record<DialogVariant, VariantClasses> = {\n default: {\n handle: 'pt-[7.5px]',\n header: 'pb-3 lg:py-4 lg:pl-6',\n body: 'py-4 lg:py-5',\n footer: 'pt-3 empty:hidden lg:py-4',\n },\n confirm: {\n handle: 'pt-[11.5px]',\n header: 'pt-3 lg:pt-6 lg:pl-6',\n body: 'pt-3',\n footer: 'not-empty:pt-5 lg:pb-6 lg:not-empty:pt-6',\n },\n};\n\nconst DEFAULT_WIDTHS: Record<DialogVariant, string> = {\n default: 'lg',\n confirm: '440px',\n};\n\n/** What started a close, as `closed` reports it. */\nexport const DIALOG_CLOSE_REASONS = ['escape', 'backdrop', 'cross', 'drag', 'programmatic'] as const;\nexport type DialogCloseReason = (typeof DIALOG_CLOSE_REASONS)[number];\n\nconst nextId = (() => {\n let count = 0;\n\n return () => `ui-dialog-${++count}`;\n})();\n\n/**\n * Modal dialog on the native <dialog>: a bottom sheet under `64rem`, centered above it.\n *\n * `busy` keeps it open while its action runs: Escape, a backdrop click and a sheet drag do nothing\n * and the cross is disabled. The owner disables its own buttons and still closes it through `open`.\n *\n * @example\n * <ui-dialog heading=\"Buy\" description=\"Ferrari\" closeLabel=\"Close\" width=\"528px\" [open]=\"buying()\" (dismissed)=\"buying.set(false)\">\n * <p>Body</p>\n * <button dialogActions ui-button variant=\"outline\" class=\"max-lg:hidden\" (click)=\"buying.set(false)\">Cancel</button>\n * <button dialogActions ui-button>Buy 40 shares</button>\n * </ui-dialog>\n */\n@Component({\n selector: 'ui-dialog',\n host: {\n '(pointerdown)': 'modal.onPointerDown($event)',\n '(click)': 'modal.onClick($event)',\n '(keydown)': 'modal.onKeydown($event)',\n },\n template: `\n <dialog\n #dlg\n [attr.aria-busy]=\"busy() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-labelledby]=\"headingId\"\n [attr.role]=\"variant() === 'confirm' ? 'alertdialog' : 'dialog'\"\n [class]=\"classes()\"\n [style.--dialog-width]=\"widthValue()\"\n (cancel)=\"modal.onCancel($event)\"\n (close)=\"modal.onNativeClose()\"\n >\n <div\n aria-hidden=\"true\"\n class=\"flex h-5 touch-none justify-center lg:hidden\"\n data-dialog-handle\n [class]=\"spec().handle\"\n >\n <span class=\"rounded-pill h-[5px] w-9 bg-(--border)\"></span>\n </div>\n\n <div data-dialog-header [class]=\"headerClasses()\">\n <div class=\"flex min-w-0 flex-1 flex-col\" [class.max-lg:pt-1]=\"description()\">\n <h2 class=\"text-title font-semibold\" [id]=\"headingId\">{{ heading() }}</h2>\n\n @if (description()) {\n <p\n class=\"text-label text-(--muted-foreground)\"\n [class.truncate]=\"truncateDescription()\"\n [id]=\"descriptionId\"\n >\n {{ description() }}\n </p>\n }\n </div>\n\n @if (closeLabel()) {\n <button\n type=\"button\"\n [attr.aria-label]=\"closeLabel()\"\n [class]=\"crossClasses\"\n [disabled]=\"busy()\"\n (click)=\"modal.close('cross')\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"block size-[22px] fill-none stroke-current stroke-[1.75]\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </button>\n }\n </div>\n\n <div\n class=\"min-h-0 flex-1 overflow-y-auto px-4 outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) lg:px-6\"\n data-dialog-body\n [attr.aria-labelledby]=\"scrollable() ? headingId : null\"\n [attr.role]=\"scrollable() ? 'region' : null\"\n [attr.tabindex]=\"scrollable() ? 0 : null\"\n [id]=\"bodyId\"\n >\n <div class=\"flex flex-col gap-4 empty:hidden\" [class]=\"spec().body\">\n <ng-content />\n </div>\n </div>\n\n <div data-dialog-footer [class]=\"footerClasses()\">\n <ng-content select=\"[dialogActions]\" />\n </div>\n </dialog>\n `,\n styles: DIALOG_STYLES,\n})\nexport class UiDialog {\n readonly heading = input.required<string>();\n readonly description = input<string>();\n readonly closeLabel = input<string>();\n readonly variant = input<DialogVariant>('default');\n readonly sheet = input<DialogSheet>('fit');\n readonly truncateDescription = input(false, { transform: booleanAttribute });\n readonly width = input<DialogWidth | (string & {})>();\n readonly open = input(false, { transform: booleanAttribute });\n readonly busy = input(false, { transform: booleanAttribute });\n readonly dismissed = output<void>();\n readonly closed = output<DialogCloseReason>();\n\n protected readonly headingId = nextId();\n protected readonly descriptionId = `${this.headingId}-description`;\n protected readonly bodyId = `${this.headingId}-body`;\n protected readonly scrollable = signal(false);\n protected readonly stacked = signal(false);\n\n protected readonly describedBy = computed(() => {\n if (this.description()) {\n return this.descriptionId;\n }\n\n return this.variant() === 'confirm' ? this.bodyId : null;\n });\n\n protected readonly widthValue = computed(() => {\n const width = this.width() ?? DEFAULT_WIDTHS[this.variant()];\n\n return Object.hasOwn(WIDTH_VALUES, width) ? WIDTH_VALUES[width as DialogWidth] : width;\n });\n\n protected readonly spec = computed(() => VARIANTS[this.variant()]);\n\n protected readonly hairlines = computed(() => Boolean(this.closeLabel()) && this.variant() === 'default');\n\n protected readonly headerClasses = computed(\n () =>\n `flex ${this.description() ? 'items-start' : 'items-center'} gap-2 pl-4 max-lg:touch-none lg:gap-3 ${this.spec().header} ${this.closeLabel() ? 'pr-2 lg:pr-4' : 'pr-4 lg:pr-6'} ${this.hairlines() ? 'shadow-[inset_0_-1px_0_var(--hairline)]' : ''}`,\n );\n\n protected readonly crossClasses =\n 'rounded-pill lg:rounded-control grid size-11 flex-none cursor-pointer place-items-center text-(--muted-foreground) transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out outline-none focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-(--ring) active:scale-(--press-scale) active:bg-(--soft) disabled:pointer-events-none disabled:opacity-40 lg:size-9 lg:hover:bg-(--glow) lg:hover:text-(--foreground)';\n\n protected readonly footerClasses = computed(\n () =>\n `max-lg:[&>[ui-button]]:text-body flex justify-end gap-2 px-4 pb-[calc(8px+env(safe-area-inset-bottom))] max-lg:flex-col-reverse max-lg:[&>[ui-button]]:h-[50px] max-lg:[&>[ui-button]]:w-full lg:px-6 ${this.spec().footer} ${this.hairlines() ? 'shadow-[inset_0_1px_0_var(--hairline)]' : ''}`,\n );\n\n protected readonly classes = computed(\n () =>\n `open:flex w-full flex-col overflow-hidden m-auto mt-auto max-lg:max-h-[calc(100dvh-2rem-env(safe-area-inset-top))] lg:max-h-[calc(100dvh-96px)] max-lg:mb-0 max-lg:max-w-none max-lg:rounded-b-none lg:max-w-(--dialog-width) rounded-container bg-(--card) text-(--foreground) outline-none shadow-[0_0_0_1px_var(--border),0_24px_64px_rgb(0_0_0/0.24)] max-lg:shadow-[0_-1px_0_var(--border),0_-12px_32px_rgb(0_0_0/0.16)] ${this.stacked() ? 'backdrop:bg-black/[0.24]' : 'backdrop:bg-black/[0.36]'} ${this.sheet() === 'full' ? 'max-lg:h-[calc(100dvh-58px)]' : ''}`,\n );\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n #drag: SheetDrag | null = null;\n\n protected readonly modal: ModalClose<DialogCloseReason>;\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n\n afterNextRender(() => {\n const host = this.#host.nativeElement;\n const dialog = host.querySelector('dialog') as HTMLDialogElement;\n const grips = ['[data-dialog-handle]', '[data-dialog-header]'].map(\n (grip) => host.querySelector(grip) as HTMLElement,\n );\n\n this.#drag = new SheetDrag(\n dialog,\n grips,\n () => this.modal.close('drag'),\n () => !this.busy(),\n );\n destroyRef.onDestroy(() => this.#drag?.destroy());\n\n if (typeof ResizeObserver === 'undefined') {\n return;\n }\n\n const body = host.querySelector('[data-dialog-body]') as HTMLElement;\n const observer = new ResizeObserver(() => this.scrollable.set(body.scrollHeight > body.clientHeight));\n\n observer.observe(body);\n observer.observe(body.firstElementChild as Element);\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n this.modal = new ModalClose<DialogCloseReason>({\n open: this.open,\n busy: this.busy,\n dismissed: this.dismissed,\n closed: this.closed,\n reset: () => this.#drag?.reset(),\n opening: () => this.stacked.set(this.#overAnotherModal()),\n });\n }\n\n #overAnotherModal(): boolean {\n const open = this.#host.nativeElement.ownerDocument.querySelectorAll('dialog[open]');\n\n return Array.from(open).some((dialog) => dialog.matches(':modal'));\n }\n}\n"],"mappings":"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"}
@@ -35,9 +35,9 @@ const PADDING_CLASSES = {
35
35
  none: "px-0"
36
36
  };
37
37
  const BASE_CLASSES = "flex w-full items-center py-1.5 rounded-control text-left select-none touch-manipulation focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring)";
38
- const INTERACTIVE_CLASSES = "transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) active:bg-(--soft) active:scale-(--press-scale)";
38
+ const INTERACTIVE_CLASSES = "cursor-pointer transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) active:bg-(--soft) active:scale-(--press-scale)";
39
39
  const CHEVRON_CLASSES = "min-h-(--row-min) gap-3 px-0 hover:text-(--muted-foreground)";
40
- const CHEVRON_INTERACTIVE_CLASSES = "transition-colors [transition-duration:var(--duration-fast)] ease-out";
40
+ const CHEVRON_INTERACTIVE_CLASSES = "cursor-pointer transition-colors [transition-duration:var(--duration-fast)] ease-out";
41
41
  const UNAVAILABLE_CLASSES = "opacity-50 cursor-not-allowed";
42
42
  const SELECTED_CLASSES = "bg-(--soft)";
43
43
  var UiRow = class UiRow {
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-row.mjs","names":[],"sources":["../../../projects/ui/row/row.ts"],"sourcesContent":["import { Component, DestroyRef, Directive, ElementRef, booleanAttribute, computed, inject, input } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\nexport const ROW_SIZES = ['md', 'lg', 'xl', 'card', 'dense'] as const;\nexport type RowSize = (typeof ROW_SIZES)[number];\n\nexport const ROW_PADDINGS = ['md', 'sm', 'none'] as const;\nexport type RowPadding = (typeof ROW_PADDINGS)[number];\n\nexport const ROW_GAPS = ['default', 'sm'] as const;\nexport type RowGap = (typeof ROW_GAPS)[number];\n\nexport const ROW_TRAILINGS = ['none', 'chevron'] as const;\nexport type RowTrailing = (typeof ROW_TRAILINGS)[number];\n\nconst SIZE_CLASSES: Record<RowSize, string> = {\n md: 'min-h-14',\n lg: 'min-h-15',\n xl: 'min-h-18 pointer-fine:min-h-17',\n card: 'min-h-17',\n dense: 'min-h-14',\n};\n\nconst SIZE_GAPS: Record<RowSize, string> = { md: 'gap-2.5', lg: 'gap-2.5', xl: 'gap-3', card: 'gap-2', dense: 'gap-3' };\n\nconst PADDING_CLASSES: Record<RowPadding, string> = { md: 'px-2.5', sm: 'px-2', none: 'px-0' };\n\nconst BASE_CLASSES =\n 'flex w-full items-center py-1.5 rounded-control text-left select-none touch-manipulation focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring)';\n\nconst INTERACTIVE_CLASSES =\n 'transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) active:bg-(--soft) active:scale-(--press-scale)';\n\nconst CHEVRON_CLASSES = 'min-h-(--row-min) gap-3 px-0 hover:text-(--muted-foreground)';\n\nconst CHEVRON_INTERACTIVE_CLASSES = 'transition-colors [transition-duration:var(--duration-fast)] ease-out';\n\nconst UNAVAILABLE_CLASSES = 'opacity-50 cursor-not-allowed';\n\nconst SELECTED_CLASSES = 'bg-(--soft)';\n\n/**\n * Clickable row of a list: a holding, an account, a search result. With `trailing=\"chevron\"` it is a\n * flush link row: no side padding, a 16 px chevron at the end, the text dimming on hover.\n *\n * @example\n * <a ui-row [selected]=\"holding.id === openId()\" [routerLink]=\"['/holdings', holding.id]\">\n * {{ holding.name }}\n * </a>\n */\n@Component({\n selector: 'a[ui-row], button[ui-row]',\n template: `\n <ng-content />\n @if (trailing() === 'chevron') {\n <svg\n aria-hidden=\"true\"\n class=\"block flex-none fill-none stroke-(--subtle-foreground)\"\n height=\"16\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"16\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n }\n @if (busy()) {\n <span\n aria-hidden=\"true\"\n class=\"rounded-pill animate-cairn-spin size-4 flex-none border-2 border-current border-r-transparent\"\n ></span>\n }\n `,\n host: {\n '[class]': 'classes()',\n '[attr.aria-busy]': 'busy() || null',\n '[attr.aria-disabled]': \"busy() || unavailable() ? 'true' : null\",\n '[attr.aria-current]': \"selected() ? 'true' : null\",\n },\n})\nexport class UiRow {\n readonly selected = input(false, { transform: booleanAttribute });\n readonly busy = input(false, { transform: booleanAttribute });\n readonly unavailable = input(false, { transform: booleanAttribute });\n readonly size = input<RowSize>('md');\n readonly padding = input<RowPadding>('md');\n readonly gap = input<RowGap>('default');\n readonly trailing = input<RowTrailing>('none');\n\n protected readonly classes = computed(() => {\n const chevron = this.trailing() === 'chevron';\n const layout = chevron\n ? CHEVRON_CLASSES\n : `${SIZE_CLASSES[this.size()]} ${this.gap() === 'sm' ? 'gap-2' : SIZE_GAPS[this.size()]} ${PADDING_CLASSES[this.padding()]}`;\n const interactive = chevron ? CHEVRON_INTERACTIVE_CLASSES : INTERACTIVE_CLASSES;\n\n return `${BASE_CLASSES} ${layout}${this.unavailable() ? ` ${UNAVAILABLE_CLASSES}` : ` ${interactive}`}${this.selected() ? ` ${SELECTED_CLASSES}` : ''}${this.busy() ? ' pointer-events-none' : ''}`;\n });\n\n constructor() {\n holdTransitionsUntilRendered();\n const host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const guard = (event: Event): void => {\n if (this.busy() || this.unavailable()) {\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n };\n\n host.addEventListener('click', guard, { capture: true });\n inject(DestroyRef).onDestroy(() => host.removeEventListener('click', guard, { capture: true }));\n }\n}\n\n/**\n * Lays out a `ui-row` with a trailing action beside it, such as a \"more\" icon button.\n *\n * @example\n * <div uiRowItem>\n * <a ui-row size=\"xl\" padding=\"sm\" routerLink=\"/accounts/1\">...</a>\n * <button ui-button variant=\"quiet\" size=\"icon-sm\" aria-label=\"Account actions\">...</button>\n * </div>\n */\n@Directive({\n selector: '[uiRowItem]',\n host: {\n class:\n 'flex items-center gap-1 [&>[ui-row]]:w-auto [&>[ui-row]]:min-w-0 [&>[ui-row]]:flex-1 [&>:not([ui-row])]:flex-none',\n },\n})\nexport class UiRowItem {}\n\n/**\n * Non-interactive row of a list, separated from the next by a hairline: a passkey with its delete\n * button, a device, a setting. Put it on an `li` or a `div`. Use `ui-row` instead when the whole\n * row is a link or an action.\n *\n * @example\n * <ul>\n * <li uiListRow>\n * <span class=\"flex-1\">MacBook Air</span>\n * <button ui-button variant=\"quiet-destructive\" size=\"icon-sm\" aria-label=\"Delete MacBook Air\">...</button>\n * </li>\n * </ul>\n */\n@Directive({\n selector: '[uiListRow]',\n host: { '[class]': 'classes()' },\n})\nexport class UiListRow {\n readonly ruled = input(true, { transform: booleanAttribute });\n\n protected readonly classes = computed(() =>\n this.ruled()\n ? 'flex min-h-18 items-center gap-3 py-1.5 lg:min-h-17 shadow-[inset_0_-1px_0_var(--hairline)]'\n : 'flex min-h-18 items-center gap-3 py-1.5 lg:min-h-17',\n );\n}\n\n/**\n * Groups link rows under a hairline, as the \"other ways\" links under a search list. Put it on a `div`\n * around `ui-row` with `trailing=\"chevron\"`.\n *\n * @example\n * <div uiRowGroup>\n * <button ui-row type=\"button\" trailing=\"chevron\">Enter manually</button>\n * </div>\n */\n@Directive({\n selector: '[uiRowGroup]',\n host: { class: 'flex flex-col pt-1 shadow-[inset_0_1px_0_var(--hairline)]' },\n})\nexport class UiRowGroup {}\n\n/**\n * The filled tile that leads a row, holding an icon. Put it on a `span` as the first child of a\n * `ui-row` or a `uiListRow`.\n *\n * @example\n * <a ui-row size=\"xl\" padding=\"sm\" href=\"/export\">\n * <span uiRowTile><svg lucideDownload [size]=\"18\" /></span>\n * Export\n * </a>\n */\n@Directive({\n selector: '[uiRowTile]',\n host: { class: 'rounded-control grid size-9 flex-none place-items-center bg-(--muted)' },\n})\nexport class UiRowTile {}\n"],"mappings":"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"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-row.mjs","names":[],"sources":["../../../projects/ui/row/row.ts"],"sourcesContent":["import { Component, DestroyRef, Directive, ElementRef, booleanAttribute, computed, inject, input } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\nexport const ROW_SIZES = ['md', 'lg', 'xl', 'card', 'dense'] as const;\nexport type RowSize = (typeof ROW_SIZES)[number];\n\nexport const ROW_PADDINGS = ['md', 'sm', 'none'] as const;\nexport type RowPadding = (typeof ROW_PADDINGS)[number];\n\nexport const ROW_GAPS = ['default', 'sm'] as const;\nexport type RowGap = (typeof ROW_GAPS)[number];\n\nexport const ROW_TRAILINGS = ['none', 'chevron'] as const;\nexport type RowTrailing = (typeof ROW_TRAILINGS)[number];\n\nconst SIZE_CLASSES: Record<RowSize, string> = {\n md: 'min-h-14',\n lg: 'min-h-15',\n xl: 'min-h-18 pointer-fine:min-h-17',\n card: 'min-h-17',\n dense: 'min-h-14',\n};\n\nconst SIZE_GAPS: Record<RowSize, string> = { md: 'gap-2.5', lg: 'gap-2.5', xl: 'gap-3', card: 'gap-2', dense: 'gap-3' };\n\nconst PADDING_CLASSES: Record<RowPadding, string> = { md: 'px-2.5', sm: 'px-2', none: 'px-0' };\n\nconst BASE_CLASSES =\n 'flex w-full items-center py-1.5 rounded-control text-left select-none touch-manipulation focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring)';\n\nconst INTERACTIVE_CLASSES =\n 'cursor-pointer transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) active:bg-(--soft) active:scale-(--press-scale)';\n\nconst CHEVRON_CLASSES = 'min-h-(--row-min) gap-3 px-0 hover:text-(--muted-foreground)';\n\nconst CHEVRON_INTERACTIVE_CLASSES =\n 'cursor-pointer transition-colors [transition-duration:var(--duration-fast)] ease-out';\n\nconst UNAVAILABLE_CLASSES = 'opacity-50 cursor-not-allowed';\n\nconst SELECTED_CLASSES = 'bg-(--soft)';\n\n/**\n * Clickable row of a list: a holding, an account, a search result. With `trailing=\"chevron\"` it is a\n * flush link row: no side padding, a 16 px chevron at the end, the text dimming on hover.\n *\n * @example\n * <a ui-row [selected]=\"holding.id === openId()\" [routerLink]=\"['/holdings', holding.id]\">\n * {{ holding.name }}\n * </a>\n */\n@Component({\n selector: 'a[ui-row], button[ui-row]',\n template: `\n <ng-content />\n @if (trailing() === 'chevron') {\n <svg\n aria-hidden=\"true\"\n class=\"block flex-none fill-none stroke-(--subtle-foreground)\"\n height=\"16\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"16\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n }\n @if (busy()) {\n <span\n aria-hidden=\"true\"\n class=\"rounded-pill animate-cairn-spin size-4 flex-none border-2 border-current border-r-transparent\"\n ></span>\n }\n `,\n host: {\n '[class]': 'classes()',\n '[attr.aria-busy]': 'busy() || null',\n '[attr.aria-disabled]': \"busy() || unavailable() ? 'true' : null\",\n '[attr.aria-current]': \"selected() ? 'true' : null\",\n },\n})\nexport class UiRow {\n readonly selected = input(false, { transform: booleanAttribute });\n readonly busy = input(false, { transform: booleanAttribute });\n readonly unavailable = input(false, { transform: booleanAttribute });\n readonly size = input<RowSize>('md');\n readonly padding = input<RowPadding>('md');\n readonly gap = input<RowGap>('default');\n readonly trailing = input<RowTrailing>('none');\n\n protected readonly classes = computed(() => {\n const chevron = this.trailing() === 'chevron';\n const layout = chevron\n ? CHEVRON_CLASSES\n : `${SIZE_CLASSES[this.size()]} ${this.gap() === 'sm' ? 'gap-2' : SIZE_GAPS[this.size()]} ${PADDING_CLASSES[this.padding()]}`;\n const interactive = chevron ? CHEVRON_INTERACTIVE_CLASSES : INTERACTIVE_CLASSES;\n\n return `${BASE_CLASSES} ${layout}${this.unavailable() ? ` ${UNAVAILABLE_CLASSES}` : ` ${interactive}`}${this.selected() ? ` ${SELECTED_CLASSES}` : ''}${this.busy() ? ' pointer-events-none' : ''}`;\n });\n\n constructor() {\n holdTransitionsUntilRendered();\n const host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n const guard = (event: Event): void => {\n if (this.busy() || this.unavailable()) {\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n };\n\n host.addEventListener('click', guard, { capture: true });\n inject(DestroyRef).onDestroy(() => host.removeEventListener('click', guard, { capture: true }));\n }\n}\n\n/**\n * Lays out a `ui-row` with a trailing action beside it, such as a \"more\" icon button.\n *\n * @example\n * <div uiRowItem>\n * <a ui-row size=\"xl\" padding=\"sm\" routerLink=\"/accounts/1\">...</a>\n * <button ui-button variant=\"quiet\" size=\"icon-sm\" aria-label=\"Account actions\">...</button>\n * </div>\n */\n@Directive({\n selector: '[uiRowItem]',\n host: {\n class:\n 'flex items-center gap-1 [&>[ui-row]]:w-auto [&>[ui-row]]:min-w-0 [&>[ui-row]]:flex-1 [&>:not([ui-row])]:flex-none',\n },\n})\nexport class UiRowItem {}\n\n/**\n * Non-interactive row of a list, separated from the next by a hairline: a passkey with its delete\n * button, a device, a setting. Put it on an `li` or a `div`. Use `ui-row` instead when the whole\n * row is a link or an action.\n *\n * @example\n * <ul>\n * <li uiListRow>\n * <span class=\"flex-1\">MacBook Air</span>\n * <button ui-button variant=\"quiet-destructive\" size=\"icon-sm\" aria-label=\"Delete MacBook Air\">...</button>\n * </li>\n * </ul>\n */\n@Directive({\n selector: '[uiListRow]',\n host: { '[class]': 'classes()' },\n})\nexport class UiListRow {\n readonly ruled = input(true, { transform: booleanAttribute });\n\n protected readonly classes = computed(() =>\n this.ruled()\n ? 'flex min-h-18 items-center gap-3 py-1.5 lg:min-h-17 shadow-[inset_0_-1px_0_var(--hairline)]'\n : 'flex min-h-18 items-center gap-3 py-1.5 lg:min-h-17',\n );\n}\n\n/**\n * Groups link rows under a hairline, as the \"other ways\" links under a search list. Put it on a `div`\n * around `ui-row` with `trailing=\"chevron\"`.\n *\n * @example\n * <div uiRowGroup>\n * <button ui-row type=\"button\" trailing=\"chevron\">Enter manually</button>\n * </div>\n */\n@Directive({\n selector: '[uiRowGroup]',\n host: { class: 'flex flex-col pt-1 shadow-[inset_0_1px_0_var(--hairline)]' },\n})\nexport class UiRowGroup {}\n\n/**\n * The filled tile that leads a row, holding an icon. Put it on a `span` as the first child of a\n * `ui-row` or a `uiListRow`.\n *\n * @example\n * <a ui-row size=\"xl\" padding=\"sm\" href=\"/export\">\n * <span uiRowTile><svg lucideDownload [size]=\"18\" /></span>\n * Export\n * </a>\n */\n@Directive({\n selector: '[uiRowTile]',\n host: { class: 'rounded-control grid size-9 flex-none place-items-center bg-(--muted)' },\n})\nexport class UiRowTile {}\n"],"mappings":"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"}
@@ -856,7 +856,7 @@ var UiRowLink = class UiRowLink {
856
856
  ...ngDevMode ? { debugName: "current" } : /* istanbul ignore next */ {},
857
857
  transform: booleanAttribute
858
858
  });
859
- classes = computed(() => this.stretch() ? "block max-w-full truncate rounded-control text-left font-medium outline-none after:absolute after:inset-0 after:rounded-control after:content-[\"\"] focus-visible:after:outline-2 focus-visible:after:-outline-offset-2 focus-visible:after:outline-(--ring)" : "block max-w-full truncate rounded-sm text-left font-medium underline-offset-[3px] outline-none hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)", ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
859
+ classes = computed(() => this.stretch() ? "block max-w-full cursor-pointer truncate rounded-control text-left font-medium outline-none after:absolute after:inset-0 after:rounded-control after:content-[\"\"] focus-visible:after:outline-2 focus-visible:after:-outline-offset-2 focus-visible:after:outline-(--ring)" : "block max-w-full cursor-pointer truncate rounded-sm text-left font-medium underline-offset-[3px] outline-none hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)", ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
860
860
  static ɵfac = i0.ɵɵngDeclareFactory({
861
861
  minVersion: "12.0.0",
862
862
  version: "22.2.2",
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-table.mjs","names":[],"sources":["../../../projects/ui/table/table.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { Component, Directive, booleanAttribute, computed, inject, input, model } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\n/** Breakpoints a secondary column can be held back until. */\nexport const CELL_BREAKPOINTS = ['md', 'lg'] as const;\nexport type CellBreakpoint = (typeof CELL_BREAKPOINTS)[number];\n\n/** Body row heights. */\nexport const TABLE_ROWS = ['48', '52', '60'] as const;\nexport type TableRow = (typeof TABLE_ROWS)[number];\n\nconst ROW_CLASSES: Record<TableRow, string> = {\n '48': '[--table-row:3rem]',\n '52': '[--table-row:3.25rem]',\n '60': '[--table-row:3.75rem]',\n};\n\nconst FROM_CLASSES: Record<CellBreakpoint, string> = {\n md: 'hidden md:table-cell',\n lg: 'hidden lg:table-cell',\n};\n\nconst TH_CLASSES =\n 'h-[calc(var(--table-head)+var(--table-head-gap))] border-b-(length:--table-head-gap) border-transparent px-2 align-middle text-caption font-medium text-(--subtle-foreground) shadow-(--table-rule)';\nconst TD_CLASSES = 'h-(--table-row) px-2 align-middle text-body';\nconst NUMERIC_CLASSES = 'text-right tabular-nums whitespace-nowrap';\nconst TEXTUAL_CLASSES = 'text-left';\nconst PRIMARY_CLASSES = 'w-full max-w-0';\n\n/**\n * Styled native table. `row` sets the height of every body row, `rule` draws or drops the hairline\n * under the header, `spaced` leaves a gap between the header and the first row.\n *\n * @example\n * <table uiTable row=\"60\" [rule]=\"false\">\n */\n@Directive({\n selector: 'table[uiTable]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class UiTable {\n readonly row = input<TableRow>('48');\n readonly rule = input(true, { transform: booleanAttribute });\n readonly spaced = input(false, { transform: booleanAttribute });\n\n protected readonly classes = computed(() =>\n [\n 'w-full border-separate border-spacing-0',\n ROW_CLASSES[this.row()],\n this.rule() ? '[--table-rule:inset_0_-1px_0_var(--hairline)]' : '[--table-rule:none]',\n this.spaced() ? '[--table-head-gap:0.25rem]' : '[--table-head-gap:0px]',\n ].join(' '),\n );\n\n constructor() {\n holdTransitionsUntilRendered();\n }\n}\n\n/**\n * Body of one group of rows. `collapsed` hides every `tr[uiTr]` but the group row with `hidden`: the rows\n * stay in the DOM, so a `uiFlipList` around the table sees no item added or removed and slides\n * nothing. A plain `tr` without `uiTr` is not hidden.\n *\n * @example\n * <tbody uiGroup [collapsed]=\"!open()\">\n */\n@Directive({\n selector: 'tbody[uiGroup]',\n host: { class: 'after:table-row after:h-1 after:content-[\"\"]' },\n})\nexport class UiGroup {\n readonly collapsed = input(false, { transform: booleanAttribute });\n}\n\n/**\n * Body or group row. `selected` takes the soft fill, `interactive` (a row that opens something) also\n * presses to it. `group` marks the row that holds a group band: it has no hover state.\n *\n * @example\n * <tr uiTr [selected]=\"open\">...\n * <tr uiTr group><td ui-group-cell name=\"Brokerage\">...\n */\n@Directive({\n selector: 'tr[uiTr]',\n host: {\n '[class]': 'classes()',\n '[attr.aria-selected]': 'selected() ? \"true\" : null',\n '[hidden]': '!group() && body?.collapsed()',\n },\n})\nexport class UiTr {\n protected readonly body = inject(UiGroup, { optional: true });\n\n readonly group = input(false, { transform: booleanAttribute });\n readonly selected = input(false, { transform: booleanAttribute });\n readonly interactive = input(false, { transform: booleanAttribute });\n\n protected readonly classes = computed(() => {\n if (this.group()) {\n return '';\n }\n return [\n 'relative [&>td:first-child]:rounded-l-control [&>td:last-child]:rounded-r-control',\n this.selected() ? '[&>td]:bg-(--soft)' : '',\n 'hover:[&>td]:bg-(--glow) [&>td]:transition-colors [&>td]:duration-(--duration-fast) [&>td]:ease-out',\n this.interactive()\n ? 'active:[&>td]:bg-(--soft) transition-transform duration-(--duration-press) ease-out active:scale-(--press-scale)'\n : '',\n ]\n .filter(Boolean)\n .join(' ');\n });\n}\n\nconst cellClasses = (\n base: string,\n numeric: boolean,\n primary: boolean,\n from: CellBreakpoint | null,\n secondary: boolean,\n): string => {\n const breakpoint = from ?? (secondary ? 'lg' : null);\n return [\n base,\n numeric ? NUMERIC_CLASSES : TEXTUAL_CLASSES,\n primary ? PRIMARY_CLASSES : '',\n breakpoint ? FROM_CLASSES[breakpoint] : '',\n ]\n .filter(Boolean)\n .join(' ');\n};\n\n/**\n * Column header. `numeric` right-aligns, `secondary` (or `from`) hides the column below a\n * breakpoint, `primary` makes it the column that absorbs the free width, `tall` is a 40px header,\n * `width` fixes the column width.\n *\n * @example\n * <th uiTh numeric secondary width=\"108px\">Quantity</th>\n */\n@Directive({\n selector: 'th[uiTh]',\n host: {\n '[class]': 'classes()',\n '[style.width]': 'width()',\n '[style.min-width]': 'width()',\n },\n})\nexport class UiTh {\n readonly width = input<string | null>(null);\n readonly numeric = input(false, { transform: booleanAttribute });\n readonly primary = input(false, { transform: booleanAttribute });\n readonly secondary = input(false, { transform: booleanAttribute });\n readonly tall = input(false, { transform: booleanAttribute });\n readonly from = input<CellBreakpoint | null>(null);\n\n protected readonly classes = computed(() =>\n cellClasses(\n `${this.tall() ? '[--table-head:2.5rem]' : '[--table-head:2.25rem]'} ${TH_CLASSES}`,\n this.numeric(),\n this.primary(),\n this.from(),\n this.secondary(),\n ),\n );\n}\n\n/**\n * Body cell. Same inputs as `UiTh` bar `tall` and `width`, which must be set on both to match.\n *\n * @example\n * <td uiTd numeric secondary>12</td>\n */\n@Directive({\n selector: 'td[uiTd]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class UiTd {\n readonly numeric = input(false, { transform: booleanAttribute });\n readonly primary = input(false, { transform: booleanAttribute });\n readonly secondary = input(false, { transform: booleanAttribute });\n readonly from = input<CellBreakpoint | null>(null);\n\n protected readonly classes = computed(() =>\n cellClasses(TD_CLASSES, this.numeric(), this.primary(), this.from(), this.secondary()),\n );\n}\n\n/** Group band sizes. */\nexport const GROUP_SIZES = ['md', 'lg'] as const;\nexport type GroupSize = (typeof GROUP_SIZES)[number];\n\n/**\n * The band that opens a group of rows: name, meta beside it, the projected total on the right.\n * Spans the whole row through `colspan`.\n *\n * With `collapsible` the band is a button inside the heading, with a chevron that turns when the\n * group is folded. `expanded` is a model: the page keeps the fold memory and sets `collapsed` on the\n * `tbody[uiGroup]`. `toggleDisabled` keeps the button focusable and announced, but a click changes\n * nothing (a filter holds the group open). `controls` is the id of the group it folds.\n *\n * @example\n * <tr uiTr group><td ui-group-cell colspan=\"4\" name=\"Brokerage\" meta=\"Savings plan\">...total...</td></tr>\n * <tr uiTr group><td ui-group-cell collapsible [(expanded)]=\"open\" controls=\"brokerage\" colspan=\"4\" name=\"Brokerage\">...</td></tr>\n */\n@Component({\n selector: 'td[ui-group-cell]',\n imports: [NgTemplateOutlet],\n host: {\n '[class]': 'hostClasses()',\n },\n template: `\n <ng-template #total><ng-content /></ng-template>\n @if (collapsible()) {\n <h2 class=\"m-0 font-normal\">\n <button\n class=\"rounded-control flex w-full items-center justify-between gap-4 bg-(--muted) px-2 text-left transition-[background-color] duration-(--duration-fast) ease-out not-aria-disabled:cursor-pointer not-aria-disabled:hover:bg-(--soft) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)\"\n data-group-heading\n type=\"button\"\n [attr.aria-controls]=\"controls() || null\"\n [attr.aria-disabled]=\"toggleDisabled() ? 'true' : null\"\n [attr.aria-expanded]=\"expanded()\"\n [class]=\"size() === 'lg' ? 'min-h-12' : 'min-h-11'\"\n (click)=\"toggle()\"\n >\n <span class=\"flex min-w-0 items-center gap-2.5\">\n <svg\n aria-hidden=\"true\"\n class=\"flex-none stroke-(--muted-foreground) transition-transform duration-(--duration-fast) ease-out\"\n fill=\"none\"\n height=\"18\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"18\"\n [class.-rotate-90]=\"!expanded()\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n <span class=\"flex min-w-0 items-baseline gap-3\">\n <span class=\"text-body font-semibold whitespace-nowrap\">{{ name() }}</span>\n @if (meta()) {\n <span class=\"text-label truncate text-(--muted-foreground)\">{{ meta() }}</span>\n }\n </span>\n </span>\n <span class=\"text-body font-semibold whitespace-nowrap tabular-nums\">\n <ng-container [ngTemplateOutlet]=\"total\" />\n </span>\n </button>\n </h2>\n } @else {\n <div\n class=\"rounded-control flex items-center justify-between gap-4 bg-(--muted) px-2\"\n [class]=\"size() === 'lg' ? 'min-h-12' : 'min-h-11'\"\n >\n <div class=\"flex min-w-0 items-baseline gap-3\">\n <h2 class=\"text-body m-0 font-semibold whitespace-nowrap outline-none\" data-group-heading tabindex=\"-1\">\n {{ name() }}\n </h2>\n @if (meta()) {\n <span class=\"text-label truncate text-(--muted-foreground)\">{{ meta() }}</span>\n }\n </div>\n <span class=\"font-semibold whitespace-nowrap tabular-nums\"><ng-container [ngTemplateOutlet]=\"total\" /></span>\n </div>\n }\n `,\n})\nexport class UiGroupCell {\n readonly name = input.required<string>();\n readonly meta = input<string>();\n readonly size = input<GroupSize>('md');\n readonly collapsible = input(false, { transform: booleanAttribute });\n readonly expanded = model(true);\n readonly toggleDisabled = input(false, { transform: booleanAttribute });\n readonly controls = input<string>();\n\n protected readonly hostClasses = computed(\n () => `px-0 ${this.size() === 'lg' ? 'pt-3' : 'pt-2.5'} pb-1 align-middle text-body`,\n );\n\n protected toggle(): void {\n if (!this.toggleDisabled()) {\n this.expanded.update((expanded) => !expanded);\n }\n }\n}\n\n/**\n * Makes a link or button the way into its row: by default it stretches over the whole row, so the\n * row is one target. With `[stretch]=\"false\"` only the name is the target. `current` marks the open\n * holding. Other controls in the row need `uiRowAction` to stay clickable.\n *\n * @example\n * <td uiTd primary><a uiRowLink href=\"/holdings/42\">Ferrari</a></td>\n * <td uiTd primary><a uiRowLink [stretch]=\"false\" href=\"/accounts/3\">Brokerage</a></td>\n */\n@Directive({\n selector: 'a[uiRowLink], button[uiRowLink]',\n host: {\n '[class]': 'classes()',\n '[attr.aria-current]': 'current() ? \"true\" : null',\n },\n})\nexport class UiRowLink {\n readonly stretch = input(true, { transform: booleanAttribute });\n readonly current = input(false, { transform: booleanAttribute });\n\n protected readonly classes = computed(() =>\n this.stretch()\n ? 'block max-w-full truncate rounded-control text-left font-medium outline-none after:absolute after:inset-0 after:rounded-control after:content-[\"\"] focus-visible:after:outline-2 focus-visible:after:-outline-offset-2 focus-visible:after:outline-(--ring)'\n : 'block max-w-full truncate rounded-sm text-left font-medium underline-offset-[3px] outline-none hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)',\n );\n}\n\n/**\n * A control in another cell of a stretched-link row: keeps it clickable above the row-wide link.\n *\n * @example\n * <td uiTd><button uiRowAction type=\"button\">Enter a price</button></td>\n */\n@Directive({\n selector: '[uiRowAction]',\n host: { class: 'relative z-1' },\n})\nexport class UiRowAction {}\n\n/** Tones of a subtitle: subtle (default), `--stale` at 500, or the color of the cell. */\nexport const SUB_TONES = ['subtle', 'stale', 'inherit'] as const;\nexport type SubTone = (typeof SUB_TONES)[number];\n\nconst SUB_TONE_CLASSES: Record<SubTone, string> = {\n subtle: 'font-normal text-(--subtle-foreground)',\n stale: 'font-medium text-(--stale)',\n inherit: 'font-normal',\n};\n\n/**\n * A second line under a cell's main text. `narrow` shows it only under 1024px, for the data held\n * back by `secondary` columns.\n *\n * @example\n * <span uiCellSub narrow>10 × 421,26 € · Avg. cost 388,10 €</span>\n * <span uiCellSub tone=\"stale\">Price as of 24/09</span>\n */\n@Directive({\n selector: '[uiCellSub]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class UiCellSub {\n readonly narrow = input(false, { transform: booleanAttribute });\n readonly tone = input<SubTone>('subtle');\n\n protected readonly classes = computed(\n () =>\n `${this.narrow() ? 'lg:hidden ' : ''}block truncate text-caption tabular-nums ${SUB_TONE_CLASSES[this.tone()]}`,\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-table.mjs","names":[],"sources":["../../../projects/ui/table/table.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport { Component, Directive, booleanAttribute, computed, inject, input, model } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\n/** Breakpoints a secondary column can be held back until. */\nexport const CELL_BREAKPOINTS = ['md', 'lg'] as const;\nexport type CellBreakpoint = (typeof CELL_BREAKPOINTS)[number];\n\n/** Body row heights. */\nexport const TABLE_ROWS = ['48', '52', '60'] as const;\nexport type TableRow = (typeof TABLE_ROWS)[number];\n\nconst ROW_CLASSES: Record<TableRow, string> = {\n '48': '[--table-row:3rem]',\n '52': '[--table-row:3.25rem]',\n '60': '[--table-row:3.75rem]',\n};\n\nconst FROM_CLASSES: Record<CellBreakpoint, string> = {\n md: 'hidden md:table-cell',\n lg: 'hidden lg:table-cell',\n};\n\nconst TH_CLASSES =\n 'h-[calc(var(--table-head)+var(--table-head-gap))] border-b-(length:--table-head-gap) border-transparent px-2 align-middle text-caption font-medium text-(--subtle-foreground) shadow-(--table-rule)';\nconst TD_CLASSES = 'h-(--table-row) px-2 align-middle text-body';\nconst NUMERIC_CLASSES = 'text-right tabular-nums whitespace-nowrap';\nconst TEXTUAL_CLASSES = 'text-left';\nconst PRIMARY_CLASSES = 'w-full max-w-0';\n\n/**\n * Styled native table. `row` sets the height of every body row, `rule` draws or drops the hairline\n * under the header, `spaced` leaves a gap between the header and the first row.\n *\n * @example\n * <table uiTable row=\"60\" [rule]=\"false\">\n */\n@Directive({\n selector: 'table[uiTable]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class UiTable {\n readonly row = input<TableRow>('48');\n readonly rule = input(true, { transform: booleanAttribute });\n readonly spaced = input(false, { transform: booleanAttribute });\n\n protected readonly classes = computed(() =>\n [\n 'w-full border-separate border-spacing-0',\n ROW_CLASSES[this.row()],\n this.rule() ? '[--table-rule:inset_0_-1px_0_var(--hairline)]' : '[--table-rule:none]',\n this.spaced() ? '[--table-head-gap:0.25rem]' : '[--table-head-gap:0px]',\n ].join(' '),\n );\n\n constructor() {\n holdTransitionsUntilRendered();\n }\n}\n\n/**\n * Body of one group of rows. `collapsed` hides every `tr[uiTr]` but the group row with `hidden`: the rows\n * stay in the DOM, so a `uiFlipList` around the table sees no item added or removed and slides\n * nothing. A plain `tr` without `uiTr` is not hidden.\n *\n * @example\n * <tbody uiGroup [collapsed]=\"!open()\">\n */\n@Directive({\n selector: 'tbody[uiGroup]',\n host: { class: 'after:table-row after:h-1 after:content-[\"\"]' },\n})\nexport class UiGroup {\n readonly collapsed = input(false, { transform: booleanAttribute });\n}\n\n/**\n * Body or group row. `selected` takes the soft fill, `interactive` (a row that opens something) also\n * presses to it. `group` marks the row that holds a group band: it has no hover state.\n *\n * @example\n * <tr uiTr [selected]=\"open\">...\n * <tr uiTr group><td ui-group-cell name=\"Brokerage\">...\n */\n@Directive({\n selector: 'tr[uiTr]',\n host: {\n '[class]': 'classes()',\n '[attr.aria-selected]': 'selected() ? \"true\" : null',\n '[hidden]': '!group() && body?.collapsed()',\n },\n})\nexport class UiTr {\n protected readonly body = inject(UiGroup, { optional: true });\n\n readonly group = input(false, { transform: booleanAttribute });\n readonly selected = input(false, { transform: booleanAttribute });\n readonly interactive = input(false, { transform: booleanAttribute });\n\n protected readonly classes = computed(() => {\n if (this.group()) {\n return '';\n }\n return [\n 'relative [&>td:first-child]:rounded-l-control [&>td:last-child]:rounded-r-control',\n this.selected() ? '[&>td]:bg-(--soft)' : '',\n 'hover:[&>td]:bg-(--glow) [&>td]:transition-colors [&>td]:duration-(--duration-fast) [&>td]:ease-out',\n this.interactive()\n ? 'active:[&>td]:bg-(--soft) transition-transform duration-(--duration-press) ease-out active:scale-(--press-scale)'\n : '',\n ]\n .filter(Boolean)\n .join(' ');\n });\n}\n\nconst cellClasses = (\n base: string,\n numeric: boolean,\n primary: boolean,\n from: CellBreakpoint | null,\n secondary: boolean,\n): string => {\n const breakpoint = from ?? (secondary ? 'lg' : null);\n return [\n base,\n numeric ? NUMERIC_CLASSES : TEXTUAL_CLASSES,\n primary ? PRIMARY_CLASSES : '',\n breakpoint ? FROM_CLASSES[breakpoint] : '',\n ]\n .filter(Boolean)\n .join(' ');\n};\n\n/**\n * Column header. `numeric` right-aligns, `secondary` (or `from`) hides the column below a\n * breakpoint, `primary` makes it the column that absorbs the free width, `tall` is a 40px header,\n * `width` fixes the column width.\n *\n * @example\n * <th uiTh numeric secondary width=\"108px\">Quantity</th>\n */\n@Directive({\n selector: 'th[uiTh]',\n host: {\n '[class]': 'classes()',\n '[style.width]': 'width()',\n '[style.min-width]': 'width()',\n },\n})\nexport class UiTh {\n readonly width = input<string | null>(null);\n readonly numeric = input(false, { transform: booleanAttribute });\n readonly primary = input(false, { transform: booleanAttribute });\n readonly secondary = input(false, { transform: booleanAttribute });\n readonly tall = input(false, { transform: booleanAttribute });\n readonly from = input<CellBreakpoint | null>(null);\n\n protected readonly classes = computed(() =>\n cellClasses(\n `${this.tall() ? '[--table-head:2.5rem]' : '[--table-head:2.25rem]'} ${TH_CLASSES}`,\n this.numeric(),\n this.primary(),\n this.from(),\n this.secondary(),\n ),\n );\n}\n\n/**\n * Body cell. Same inputs as `UiTh` bar `tall` and `width`, which must be set on both to match.\n *\n * @example\n * <td uiTd numeric secondary>12</td>\n */\n@Directive({\n selector: 'td[uiTd]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class UiTd {\n readonly numeric = input(false, { transform: booleanAttribute });\n readonly primary = input(false, { transform: booleanAttribute });\n readonly secondary = input(false, { transform: booleanAttribute });\n readonly from = input<CellBreakpoint | null>(null);\n\n protected readonly classes = computed(() =>\n cellClasses(TD_CLASSES, this.numeric(), this.primary(), this.from(), this.secondary()),\n );\n}\n\n/** Group band sizes. */\nexport const GROUP_SIZES = ['md', 'lg'] as const;\nexport type GroupSize = (typeof GROUP_SIZES)[number];\n\n/**\n * The band that opens a group of rows: name, meta beside it, the projected total on the right.\n * Spans the whole row through `colspan`.\n *\n * With `collapsible` the band is a button inside the heading, with a chevron that turns when the\n * group is folded. `expanded` is a model: the page keeps the fold memory and sets `collapsed` on the\n * `tbody[uiGroup]`. `toggleDisabled` keeps the button focusable and announced, but a click changes\n * nothing (a filter holds the group open). `controls` is the id of the group it folds.\n *\n * @example\n * <tr uiTr group><td ui-group-cell colspan=\"4\" name=\"Brokerage\" meta=\"Savings plan\">...total...</td></tr>\n * <tr uiTr group><td ui-group-cell collapsible [(expanded)]=\"open\" controls=\"brokerage\" colspan=\"4\" name=\"Brokerage\">...</td></tr>\n */\n@Component({\n selector: 'td[ui-group-cell]',\n imports: [NgTemplateOutlet],\n host: {\n '[class]': 'hostClasses()',\n },\n template: `\n <ng-template #total><ng-content /></ng-template>\n @if (collapsible()) {\n <h2 class=\"m-0 font-normal\">\n <button\n class=\"rounded-control flex w-full items-center justify-between gap-4 bg-(--muted) px-2 text-left transition-[background-color] duration-(--duration-fast) ease-out not-aria-disabled:cursor-pointer not-aria-disabled:hover:bg-(--soft) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)\"\n data-group-heading\n type=\"button\"\n [attr.aria-controls]=\"controls() || null\"\n [attr.aria-disabled]=\"toggleDisabled() ? 'true' : null\"\n [attr.aria-expanded]=\"expanded()\"\n [class]=\"size() === 'lg' ? 'min-h-12' : 'min-h-11'\"\n (click)=\"toggle()\"\n >\n <span class=\"flex min-w-0 items-center gap-2.5\">\n <svg\n aria-hidden=\"true\"\n class=\"flex-none stroke-(--muted-foreground) transition-transform duration-(--duration-fast) ease-out\"\n fill=\"none\"\n height=\"18\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n width=\"18\"\n [class.-rotate-90]=\"!expanded()\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n <span class=\"flex min-w-0 items-baseline gap-3\">\n <span class=\"text-body font-semibold whitespace-nowrap\">{{ name() }}</span>\n @if (meta()) {\n <span class=\"text-label truncate text-(--muted-foreground)\">{{ meta() }}</span>\n }\n </span>\n </span>\n <span class=\"text-body font-semibold whitespace-nowrap tabular-nums\">\n <ng-container [ngTemplateOutlet]=\"total\" />\n </span>\n </button>\n </h2>\n } @else {\n <div\n class=\"rounded-control flex items-center justify-between gap-4 bg-(--muted) px-2\"\n [class]=\"size() === 'lg' ? 'min-h-12' : 'min-h-11'\"\n >\n <div class=\"flex min-w-0 items-baseline gap-3\">\n <h2 class=\"text-body m-0 font-semibold whitespace-nowrap outline-none\" data-group-heading tabindex=\"-1\">\n {{ name() }}\n </h2>\n @if (meta()) {\n <span class=\"text-label truncate text-(--muted-foreground)\">{{ meta() }}</span>\n }\n </div>\n <span class=\"font-semibold whitespace-nowrap tabular-nums\"><ng-container [ngTemplateOutlet]=\"total\" /></span>\n </div>\n }\n `,\n})\nexport class UiGroupCell {\n readonly name = input.required<string>();\n readonly meta = input<string>();\n readonly size = input<GroupSize>('md');\n readonly collapsible = input(false, { transform: booleanAttribute });\n readonly expanded = model(true);\n readonly toggleDisabled = input(false, { transform: booleanAttribute });\n readonly controls = input<string>();\n\n protected readonly hostClasses = computed(\n () => `px-0 ${this.size() === 'lg' ? 'pt-3' : 'pt-2.5'} pb-1 align-middle text-body`,\n );\n\n protected toggle(): void {\n if (!this.toggleDisabled()) {\n this.expanded.update((expanded) => !expanded);\n }\n }\n}\n\n/**\n * Makes a link or button the way into its row: by default it stretches over the whole row, so the\n * row is one target. With `[stretch]=\"false\"` only the name is the target. `current` marks the open\n * holding. Other controls in the row need `uiRowAction` to stay clickable.\n *\n * @example\n * <td uiTd primary><a uiRowLink href=\"/holdings/42\">Ferrari</a></td>\n * <td uiTd primary><a uiRowLink [stretch]=\"false\" href=\"/accounts/3\">Brokerage</a></td>\n */\n@Directive({\n selector: 'a[uiRowLink], button[uiRowLink]',\n host: {\n '[class]': 'classes()',\n '[attr.aria-current]': 'current() ? \"true\" : null',\n },\n})\nexport class UiRowLink {\n readonly stretch = input(true, { transform: booleanAttribute });\n readonly current = input(false, { transform: booleanAttribute });\n\n protected readonly classes = computed(() =>\n this.stretch()\n ? 'block max-w-full cursor-pointer truncate rounded-control text-left font-medium outline-none after:absolute after:inset-0 after:rounded-control after:content-[\"\"] focus-visible:after:outline-2 focus-visible:after:-outline-offset-2 focus-visible:after:outline-(--ring)'\n : 'block max-w-full cursor-pointer truncate rounded-sm text-left font-medium underline-offset-[3px] outline-none hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)',\n );\n}\n\n/**\n * A control in another cell of a stretched-link row: keeps it clickable above the row-wide link.\n *\n * @example\n * <td uiTd><button uiRowAction type=\"button\">Enter a price</button></td>\n */\n@Directive({\n selector: '[uiRowAction]',\n host: { class: 'relative z-1' },\n})\nexport class UiRowAction {}\n\n/** Tones of a subtitle: subtle (default), `--stale` at 500, or the color of the cell. */\nexport const SUB_TONES = ['subtle', 'stale', 'inherit'] as const;\nexport type SubTone = (typeof SUB_TONES)[number];\n\nconst SUB_TONE_CLASSES: Record<SubTone, string> = {\n subtle: 'font-normal text-(--subtle-foreground)',\n stale: 'font-medium text-(--stale)',\n inherit: 'font-normal',\n};\n\n/**\n * A second line under a cell's main text. `narrow` shows it only under 1024px, for the data held\n * back by `secondary` columns.\n *\n * @example\n * <span uiCellSub narrow>10 × 421,26 € · Avg. cost 388,10 €</span>\n * <span uiCellSub tone=\"stale\">Price as of 24/09</span>\n */\n@Directive({\n selector: '[uiCellSub]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class UiCellSub {\n readonly narrow = input(false, { transform: booleanAttribute });\n readonly tone = input<SubTone>('subtle');\n\n protected readonly classes = computed(\n () =>\n `${this.narrow() ? 'lg:hidden ' : ''}block truncate text-caption tabular-nums ${SUB_TONE_CLASSES[this.tone()]}`,\n );\n}\n"],"mappings":"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"}