@joanroucoux/cairn-ui 0.10.0 → 0.10.1

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +2 -0
  3. package/fesm2022/joanroucoux-cairn-ui-async.mjs.map +1 -1
  4. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs.map +1 -1
  5. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs.map +1 -1
  6. package/fesm2022/joanroucoux-cairn-ui-donut.mjs +4 -4
  7. package/fesm2022/joanroucoux-cairn-ui-donut.mjs.map +1 -1
  8. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs.map +1 -1
  9. package/fesm2022/joanroucoux-cairn-ui-empty.mjs.map +1 -1
  10. package/fesm2022/joanroucoux-cairn-ui-fact.mjs.map +1 -1
  11. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs.map +1 -1
  12. package/fesm2022/joanroucoux-cairn-ui-input.mjs.map +1 -1
  13. package/fesm2022/joanroucoux-cairn-ui-menu.mjs +8 -1
  14. package/fesm2022/joanroucoux-cairn-ui-menu.mjs.map +1 -1
  15. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs.map +1 -1
  16. package/fesm2022/joanroucoux-cairn-ui-row.mjs.map +1 -1
  17. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs.map +1 -1
  18. package/fesm2022/joanroucoux-cairn-ui-table.mjs.map +1 -1
  19. package/fesm2022/joanroucoux-cairn-ui-toast.mjs +1 -1
  20. package/fesm2022/joanroucoux-cairn-ui-toast.mjs.map +1 -1
  21. package/mcp-manifest.json +1 -0
  22. package/package.json +5 -2
  23. package/types/joanroucoux-cairn-ui-async.d.ts +3 -3
  24. package/types/joanroucoux-cairn-ui-choice-chips.d.ts +2 -2
  25. package/types/joanroucoux-cairn-ui-dialog.d.ts +3 -0
  26. package/types/joanroucoux-cairn-ui-donut.d.ts +1 -1
  27. package/types/joanroucoux-cairn-ui-drawer.d.ts +1 -1
  28. package/types/joanroucoux-cairn-ui-empty.d.ts +3 -3
  29. package/types/joanroucoux-cairn-ui-fact.d.ts +1 -1
  30. package/types/joanroucoux-cairn-ui-group-header.d.ts +1 -1
  31. package/types/joanroucoux-cairn-ui-input.d.ts +3 -0
  32. package/types/joanroucoux-cairn-ui-menu.d.ts +3 -3
  33. package/types/joanroucoux-cairn-ui-result-group.d.ts +3 -3
  34. package/types/joanroucoux-cairn-ui-row.d.ts +1 -1
  35. package/types/joanroucoux-cairn-ui-stale-link.d.ts +2 -2
  36. package/types/joanroucoux-cairn-ui-table.d.ts +16 -6
  37. package/types/joanroucoux-cairn-ui-toast.d.ts +3 -3
@@ -184,11 +184,18 @@ var UiMenu = class UiMenu {
184
184
  #isSheet() {
185
185
  return this.sheet() && typeof window.matchMedia === "function" && !window.matchMedia("(min-width: 64rem)").matches;
186
186
  }
187
+ #layoutWidth() {
188
+ const style = getComputedStyle(this.#host);
189
+ const width = parseFloat(style.width);
190
+ if (Number.isNaN(width)) return this.#host.offsetWidth;
191
+ if (style.boxSizing === "border-box") return width;
192
+ return width + parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth);
193
+ }
187
194
  #position(trigger) {
188
195
  const margin = 8;
189
196
  const triggerRect = trigger.getBoundingClientRect();
190
197
  const menuRect = {
191
- width: this.#host.offsetWidth,
198
+ width: this.#layoutWidth(),
192
199
  height: this.#host.offsetHeight
193
200
  };
194
201
  const fitsBelow = window.innerHeight - triggerRect.bottom >= menuRect.height + margin;
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-menu.mjs","names":[],"sources":["../../../projects/ui/menu/menu.ts"],"sourcesContent":["import {\n Component,\n Directive,\n ElementRef,\n booleanAttribute,\n computed,\n contentChildren,\n inject,\n input,\n numberAttribute,\n signal,\n} from '@angular/core';\n\nconst MENU_CLASSES =\n 'm-0 min-w-44 p-1 rounded-container bg-(--elevated) shadow-[0_8px_24px_rgb(0_0_0/0.16),inset_0_0_0_1px_var(--border)] text-(--foreground) transition-[opacity,scale,overlay,display] transition-discrete duration-(--duration-fast) not-open:duration-[120ms] ease-out starting:open:opacity-0 starting:open:scale-(--enter-scale) opacity-0 scale-(--enter-scale) open:opacity-100 open:scale-100';\n\nconst SHEET_CLASSES =\n 'max-lg:fixed max-lg:inset-x-4 max-lg:top-auto max-lg:w-auto max-lg:bottom-[calc(76px+env(safe-area-inset-bottom))] max-lg:min-w-0 max-lg:p-1.5 max-lg:bg-(--card) max-lg:shadow-[0_12px_32px_rgb(0_0_0/0.2),inset_0_0_0_1px_var(--border)] max-lg:backdrop:bg-[rgb(0_0_0/0.36)] max-lg:transition-[opacity,translate,overlay,display] max-lg:scale-100 max-lg:translate-y-4 max-lg:open:translate-y-0 max-lg:starting:open:scale-100 max-lg:starting:open:translate-y-4 max-lg:motion-reduce:translate-y-0 max-lg:motion-reduce:starting:open:translate-y-0';\n\nconst SHEET_ITEM_CLASSES =\n 'flex w-full items-center gap-3 lg:pointer-fine:gap-2.5 min-h-12 lg:min-h-11 lg:pointer-fine:min-h-9 px-3 lg:pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-6px)] lg:rounded-[calc(var(--radius-container)-4px)] text-body lg:pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-5 [:where(&>svg)]:flex-none lg:[:where(&>svg)]:size-[18px] lg:pointer-fine:[:where(&>svg)]:size-4';\n\nconst ITEM_CLASSES =\n 'flex w-full items-center gap-3 pointer-fine:gap-2.5 min-h-11 pointer-fine:min-h-9 px-3 pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-4px)] text-body pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-[18px] [:where(&>svg)]:flex-none pointer-fine:[:where(&>svg)]:size-4';\n\nconst CHECK_CLASSES =\n \"after:ms-auto after:block after:h-3 after:w-1.5 after:flex-none after:rotate-45 after:border-r-2 after:border-b-2 after:border-current after:content-['']\";\n\nconst nextId = (() => {\n let count = 0;\n\n return () => `ui-menu-${++count}`;\n})();\n\n/**\n * One action of a `ui-menu`; `destructive` paints it in `--negative`. Giving it `checked` makes it a radio\n * choice (`menuitemradio`): the current one carries a check mark and `aria-checked=\"true\"`.\n *\n * @example\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the line</button>\n * <button uiMenuItem [checked]=\"account() === 'pea'\" (click)=\"account.set('pea')\">Northwind PEA</button>\n */\n@Directive({\n selector: 'button[uiMenuItem]',\n host: {\n '[attr.role]': 'role()',\n '[attr.aria-checked]': 'checked() === undefined ? null : checked()',\n tabindex: '-1',\n '[class]': 'classes()',\n '(click)': 'onClick()',\n },\n})\nexport class UiMenuItem {\n readonly destructive = input(false, { transform: booleanAttribute });\n readonly checked = input<boolean>();\n\n readonly #host = inject<ElementRef<HTMLButtonElement>>(ElementRef).nativeElement;\n readonly #menu = inject(UiMenu);\n\n protected readonly role = computed(() => (this.checked() === undefined ? 'menuitem' : 'menuitemradio'));\n\n protected readonly classes = computed(\n () =>\n `${this.#menu.sheet() ? SHEET_ITEM_CLASSES : ITEM_CLASSES}${this.destructive() ? ' text-(--negative)' : ''}${this.checked() ? ` ${CHECK_CLASSES}` : ''}`,\n );\n\n focus(): void {\n this.#host.focus();\n }\n\n hasFocus(): boolean {\n return this.#host === document.activeElement;\n }\n\n protected onClick(): void {\n this.#menu.close();\n }\n}\n\n/**\n * Secondary actions menu, opened from its trigger through the native Popover API. With `sheet`, below\n * 64rem it opens as a bottom action sheet instead of beside its trigger, and `heading` names what\n * the actions apply to. `width` fixes the popover width in pixels; without it the menu fits its content.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n * <ui-menu #menu label=\"Line actions\">\n * <button uiMenuItem (click)=\"edit()\">Edit</button>\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the line</button>\n * </ui-menu>\n */\n@Component({\n selector: 'ui-menu',\n template: `\n @if (sheet() && heading()) {\n <div aria-hidden=\"true\" class=\"text-label px-3 pt-2 pb-1.5 leading-[17px] text-(--muted-foreground) lg:hidden\">\n {{ heading() }}\n </div>\n }\n <ng-content />\n `,\n host: {\n role: 'menu',\n popover: 'auto',\n '[id]': 'menuId',\n '[style.--ui-menu-width]': 'widthVar()',\n '[class]': 'classes()',\n '[attr.aria-label]': 'label()',\n '(toggle)': 'onToggle($event)',\n '(keydown)': 'onKeydown($event)',\n },\n})\nexport class UiMenu {\n readonly label = input.required<string>();\n readonly sheet = input(false, { transform: booleanAttribute });\n readonly heading = input<string>();\n readonly width = input<number | undefined, unknown>(undefined, { transform: numberAttribute });\n\n readonly menuId = nextId();\n readonly isOpen = signal(false);\n\n protected readonly hasWidth = computed(() => Number.isFinite(this.width()));\n protected readonly widthVar = computed(() => (this.hasWidth() ? `${this.width()}px` : null));\n protected readonly classes = computed(() => {\n const width = !this.hasWidth() ? '' : this.sheet() ? ' lg:w-(--ui-menu-width)' : ' w-(--ui-menu-width)';\n return `${MENU_CLASSES}${this.sheet() ? ` ${SHEET_CLASSES}` : ''}${width}`;\n });\n protected readonly items = contentChildren(UiMenuItem);\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n #trigger: HTMLElement | null = null;\n\n open(trigger: HTMLElement): void {\n this.#trigger = trigger;\n this.isOpen.set(true);\n if (typeof this.#host.showPopover === 'function') {\n this.#host.showPopover();\n }\n if (this.#isSheet()) {\n this.#host.style.position = '';\n this.#host.style.top = '';\n this.#host.style.left = '';\n this.#host.style.right = '';\n this.#host.style.bottom = '';\n } else {\n this.#position(trigger);\n }\n (this.items().find((item) => item.checked()) ?? this.items()[0])?.focus();\n }\n\n close(): void {\n const wasOpen = this.isOpen();\n\n this.#applyClosed();\n\n if (wasOpen && typeof this.#host.hidePopover === 'function') {\n this.#host.hidePopover();\n }\n }\n\n #applyClosed(): void {\n this.isOpen.set(false);\n this.#trigger?.focus();\n this.#trigger = null;\n }\n\n protected onToggle(event: Event): void {\n if ((event as ToggleEvent).newState === 'closed') {\n this.#applyClosed();\n }\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Tab' || event.key === 'Escape') {\n event.preventDefault();\n this.close();\n return;\n }\n\n const items = this.items();\n const currentIndex = items.findIndex((item) => item.hasFocus());\n const lastIndex = items.length - 1;\n\n let nextIndex: number | undefined;\n switch (event.key) {\n case 'ArrowDown':\n nextIndex = currentIndex >= lastIndex ? 0 : currentIndex + 1;\n break;\n case 'ArrowUp':\n nextIndex = currentIndex <= 0 ? lastIndex : currentIndex - 1;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = lastIndex;\n break;\n }\n\n if (nextIndex === undefined) {\n return;\n }\n event.preventDefault();\n items[nextIndex]?.focus();\n }\n\n #isSheet(): boolean {\n return this.sheet() && typeof window.matchMedia === 'function' && !window.matchMedia('(min-width: 64rem)').matches;\n }\n\n #position(trigger: HTMLElement): void {\n const margin = 8;\n const triggerRect = trigger.getBoundingClientRect();\n const menuRect = { width: this.#host.offsetWidth, height: this.#host.offsetHeight };\n const fitsBelow = window.innerHeight - triggerRect.bottom >= menuRect.height + margin;\n\n const top = fitsBelow ? triggerRect.bottom + 4 : Math.max(margin, triggerRect.top - menuRect.height - 4);\n const left = Math.min(\n Math.max(triggerRect.right - menuRect.width, margin),\n window.innerWidth - menuRect.width - margin,\n );\n\n this.#host.style.position = 'fixed';\n this.#host.style.top = `${Math.min(top, window.innerHeight - menuRect.height - margin)}px`;\n this.#host.style.left = `${left}px`;\n this.#host.style.right = 'auto';\n this.#host.style.bottom = 'auto';\n this.#host.style.transformOrigin = fitsBelow ? 'top right' : 'bottom right';\n }\n}\n\n/**\n * Opens a `ui-menu` from a trigger element and wires its ARIA attributes.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n */\n@Directive({\n selector: '[uiMenuTrigger]',\n host: {\n 'aria-haspopup': 'menu',\n '[attr.aria-expanded]': 'uiMenuTrigger().isOpen()',\n '[attr.aria-controls]': 'uiMenuTrigger().menuId',\n '(click)': 'toggle()',\n },\n})\nexport class UiMenuTrigger {\n readonly uiMenuTrigger = input.required<UiMenu>();\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n protected toggle(): void {\n const menu = this.uiMenuTrigger();\n\n if (menu.isOpen()) {\n menu.close();\n } else {\n menu.open(this.#host);\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-menu.mjs","names":[],"sources":["../../../projects/ui/menu/menu.ts"],"sourcesContent":["import {\n Component,\n Directive,\n ElementRef,\n booleanAttribute,\n computed,\n contentChildren,\n inject,\n input,\n numberAttribute,\n signal,\n} from '@angular/core';\n\nconst MENU_CLASSES =\n 'm-0 min-w-44 p-1 rounded-container bg-(--elevated) shadow-[0_8px_24px_rgb(0_0_0/0.16),inset_0_0_0_1px_var(--border)] text-(--foreground) transition-[opacity,scale,overlay,display] transition-discrete duration-(--duration-fast) not-open:duration-[120ms] ease-out starting:open:opacity-0 starting:open:scale-(--enter-scale) opacity-0 scale-(--enter-scale) open:opacity-100 open:scale-100';\n\nconst SHEET_CLASSES =\n 'max-lg:fixed max-lg:inset-x-4 max-lg:top-auto max-lg:w-auto max-lg:bottom-[calc(76px+env(safe-area-inset-bottom))] max-lg:min-w-0 max-lg:p-1.5 max-lg:bg-(--card) max-lg:shadow-[0_12px_32px_rgb(0_0_0/0.2),inset_0_0_0_1px_var(--border)] max-lg:backdrop:bg-[rgb(0_0_0/0.36)] max-lg:transition-[opacity,translate,overlay,display] max-lg:scale-100 max-lg:translate-y-4 max-lg:open:translate-y-0 max-lg:starting:open:scale-100 max-lg:starting:open:translate-y-4 max-lg:motion-reduce:translate-y-0 max-lg:motion-reduce:starting:open:translate-y-0';\n\nconst SHEET_ITEM_CLASSES =\n 'flex w-full items-center gap-3 lg:pointer-fine:gap-2.5 min-h-12 lg:min-h-11 lg:pointer-fine:min-h-9 px-3 lg:pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-6px)] lg:rounded-[calc(var(--radius-container)-4px)] text-body lg:pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-5 [:where(&>svg)]:flex-none lg:[:where(&>svg)]:size-[18px] lg:pointer-fine:[:where(&>svg)]:size-4';\n\nconst ITEM_CLASSES =\n 'flex w-full items-center gap-3 pointer-fine:gap-2.5 min-h-11 pointer-fine:min-h-9 px-3 pointer-fine:px-2.5 rounded-[calc(var(--radius-container)-4px)] text-body pointer-fine:text-label text-left whitespace-nowrap hover:bg-(--glow) focus-visible:bg-(--glow) active:bg-(--soft) transition-[background-color] duration-(--duration-fast) ease-out outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-(--ring) [:where(&>svg)]:size-[18px] [:where(&>svg)]:flex-none pointer-fine:[:where(&>svg)]:size-4';\n\nconst CHECK_CLASSES =\n \"after:ms-auto after:block after:h-3 after:w-1.5 after:flex-none after:rotate-45 after:border-r-2 after:border-b-2 after:border-current after:content-['']\";\n\nconst nextId = (() => {\n let count = 0;\n\n return () => `ui-menu-${++count}`;\n})();\n\n/**\n * One action of a `ui-menu`; `destructive` paints it in `--negative`. Giving it `checked` makes it a radio\n * choice (`menuitemradio`): the current one carries a check mark and `aria-checked=\"true\"`.\n *\n * @example\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the holding</button>\n * <button uiMenuItem [checked]=\"account() === 'pea'\" (click)=\"account.set('pea')\">Northwind PEA</button>\n */\n@Directive({\n selector: 'button[uiMenuItem]',\n host: {\n '[attr.role]': 'role()',\n '[attr.aria-checked]': 'checked() === undefined ? null : checked()',\n tabindex: '-1',\n '[class]': 'classes()',\n '(click)': 'onClick()',\n },\n})\nexport class UiMenuItem {\n readonly destructive = input(false, { transform: booleanAttribute });\n readonly checked = input<boolean>();\n\n readonly #host = inject<ElementRef<HTMLButtonElement>>(ElementRef).nativeElement;\n readonly #menu = inject(UiMenu);\n\n protected readonly role = computed(() => (this.checked() === undefined ? 'menuitem' : 'menuitemradio'));\n\n protected readonly classes = computed(\n () =>\n `${this.#menu.sheet() ? SHEET_ITEM_CLASSES : ITEM_CLASSES}${this.destructive() ? ' text-(--negative)' : ''}${this.checked() ? ` ${CHECK_CLASSES}` : ''}`,\n );\n\n focus(): void {\n this.#host.focus();\n }\n\n hasFocus(): boolean {\n return this.#host === document.activeElement;\n }\n\n protected onClick(): void {\n this.#menu.close();\n }\n}\n\n/**\n * Secondary actions menu, opened from its trigger through the native Popover API. With `sheet`, below\n * 64rem it opens as a bottom action sheet instead of beside its trigger, and `heading` names what\n * the actions apply to. `width` fixes the popover width in pixels; without it the menu fits its content.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n * <ui-menu #menu label=\"Holding actions\">\n * <button uiMenuItem (click)=\"edit()\">Edit</button>\n * <button uiMenuItem destructive (click)=\"remove()\">Delete the holding</button>\n * </ui-menu>\n */\n@Component({\n selector: 'ui-menu',\n template: `\n @if (sheet() && heading()) {\n <div aria-hidden=\"true\" class=\"text-label px-3 pt-2 pb-1.5 leading-[17px] text-(--muted-foreground) lg:hidden\">\n {{ heading() }}\n </div>\n }\n <ng-content />\n `,\n host: {\n role: 'menu',\n popover: 'auto',\n '[id]': 'menuId',\n '[style.--ui-menu-width]': 'widthVar()',\n '[class]': 'classes()',\n '[attr.aria-label]': 'label()',\n '(toggle)': 'onToggle($event)',\n '(keydown)': 'onKeydown($event)',\n },\n})\nexport class UiMenu {\n readonly label = input.required<string>();\n readonly sheet = input(false, { transform: booleanAttribute });\n readonly heading = input<string>();\n readonly width = input<number | undefined, unknown>(undefined, { transform: numberAttribute });\n\n readonly menuId = nextId();\n readonly isOpen = signal(false);\n\n protected readonly hasWidth = computed(() => Number.isFinite(this.width()));\n protected readonly widthVar = computed(() => (this.hasWidth() ? `${this.width()}px` : null));\n protected readonly classes = computed(() => {\n const width = !this.hasWidth() ? '' : this.sheet() ? ' lg:w-(--ui-menu-width)' : ' w-(--ui-menu-width)';\n return `${MENU_CLASSES}${this.sheet() ? ` ${SHEET_CLASSES}` : ''}${width}`;\n });\n protected readonly items = contentChildren(UiMenuItem);\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n #trigger: HTMLElement | null = null;\n\n open(trigger: HTMLElement): void {\n this.#trigger = trigger;\n this.isOpen.set(true);\n if (typeof this.#host.showPopover === 'function') {\n this.#host.showPopover();\n }\n if (this.#isSheet()) {\n this.#host.style.position = '';\n this.#host.style.top = '';\n this.#host.style.left = '';\n this.#host.style.right = '';\n this.#host.style.bottom = '';\n } else {\n this.#position(trigger);\n }\n (this.items().find((item) => item.checked()) ?? this.items()[0])?.focus();\n }\n\n close(): void {\n const wasOpen = this.isOpen();\n\n this.#applyClosed();\n\n if (wasOpen && typeof this.#host.hidePopover === 'function') {\n this.#host.hidePopover();\n }\n }\n\n #applyClosed(): void {\n this.isOpen.set(false);\n this.#trigger?.focus();\n this.#trigger = null;\n }\n\n protected onToggle(event: Event): void {\n if ((event as ToggleEvent).newState === 'closed') {\n this.#applyClosed();\n }\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Tab' || event.key === 'Escape') {\n event.preventDefault();\n this.close();\n return;\n }\n\n const items = this.items();\n const currentIndex = items.findIndex((item) => item.hasFocus());\n const lastIndex = items.length - 1;\n\n let nextIndex: number | undefined;\n switch (event.key) {\n case 'ArrowDown':\n nextIndex = currentIndex >= lastIndex ? 0 : currentIndex + 1;\n break;\n case 'ArrowUp':\n nextIndex = currentIndex <= 0 ? lastIndex : currentIndex - 1;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = lastIndex;\n break;\n }\n\n if (nextIndex === undefined) {\n return;\n }\n event.preventDefault();\n items[nextIndex]?.focus();\n }\n\n #isSheet(): boolean {\n return this.sheet() && typeof window.matchMedia === 'function' && !window.matchMedia('(min-width: 64rem)').matches;\n }\n\n #layoutWidth(): number {\n const style = getComputedStyle(this.#host);\n const width = parseFloat(style.width);\n\n if (Number.isNaN(width)) {\n return this.#host.offsetWidth;\n }\n\n if (style.boxSizing === 'border-box') {\n return width;\n }\n\n return (\n width +\n parseFloat(style.paddingLeft) +\n parseFloat(style.paddingRight) +\n parseFloat(style.borderLeftWidth) +\n parseFloat(style.borderRightWidth)\n );\n }\n\n #position(trigger: HTMLElement): void {\n const margin = 8;\n const triggerRect = trigger.getBoundingClientRect();\n const menuRect = { width: this.#layoutWidth(), height: this.#host.offsetHeight };\n const fitsBelow = window.innerHeight - triggerRect.bottom >= menuRect.height + margin;\n\n const top = fitsBelow ? triggerRect.bottom + 4 : Math.max(margin, triggerRect.top - menuRect.height - 4);\n const left = Math.min(\n Math.max(triggerRect.right - menuRect.width, margin),\n window.innerWidth - menuRect.width - margin,\n );\n\n this.#host.style.position = 'fixed';\n this.#host.style.top = `${Math.min(top, window.innerHeight - menuRect.height - margin)}px`;\n this.#host.style.left = `${left}px`;\n this.#host.style.right = 'auto';\n this.#host.style.bottom = 'auto';\n this.#host.style.transformOrigin = fitsBelow ? 'top right' : 'bottom right';\n }\n}\n\n/**\n * Opens a `ui-menu` from a trigger element and wires its ARIA attributes.\n *\n * @example\n * <button ui-button size=\"icon\" aria-label=\"More\" [uiMenuTrigger]=\"menu\">...</button>\n */\n@Directive({\n selector: '[uiMenuTrigger]',\n host: {\n 'aria-haspopup': 'menu',\n '[attr.aria-expanded]': 'uiMenuTrigger().isOpen()',\n '[attr.aria-controls]': 'uiMenuTrigger().menuId',\n '(click)': 'toggle()',\n },\n})\nexport class UiMenuTrigger {\n readonly uiMenuTrigger = input.required<UiMenu>();\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n protected toggle(): void {\n const menu = this.uiMenuTrigger();\n\n if (menu.isOpen()) {\n menu.close();\n } else {\n menu.open(this.#host);\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-result-group.mjs","names":[],"sources":["../../../projects/ui/result-group/result-group.ts"],"sourcesContent":["import { Component, computed, input, output } from '@angular/core';\n\nimport { type AsyncState, UiAsync } from '@joanroucoux/cairn-ui/async';\n\nconst PULSE_ANIMATION = 'cairn-pulse var(--pulse-duration) var(--ease-out) infinite alternate';\n\nconst BAR_CLASSES = 'block h-4 rounded-control bg-(--muted)';\n\n/**\n * One source of a search: a two-tone heading, then its rows, or a skeleton while it answers, a\n * message when it has nothing, or an inline error with a retry.\n *\n * @example\n * <ui-result-group label=\"Yahoo Finance\" hint=\"cours en continu\" [state]=\"state()\"\n * errorMessage=\"Yahoo Finance n'a pas répondu.\" retryLabel=\"Réessayer\" (retry)=\"search()\">\n * <button ui-row size=\"dense\" type=\"button\">...</button>\n * <span resultGroupMessage>Aucun résultat chez Yahoo Finance.</span>\n * </ui-result-group>\n */\n@Component({\n selector: 'ui-result-group',\n imports: [UiAsync],\n template: `\n <div class=\"text-caption flex items-baseline gap-1.5 pt-3 pr-2.5 pb-1 pl-2.5 tracking-(--tracking-caption)\">\n <span class=\"font-semibold text-(--foreground)\">{{ label() }}</span>\n @if (hint()) {\n <span class=\"text-(--subtle-foreground)\">{{ hint() }}</span>\n }\n </div>\n <ui-async\n variant=\"inline\"\n [errorMessage]=\"errorMessage()\"\n [retryIcon]=\"false\"\n [retryLabel]=\"retryLabel()\"\n [state]=\"state()\"\n (retry)=\"retry.emit()\"\n >\n <div asyncLoading class=\"flex flex-col gap-3.5 px-2.5 pt-2.5 pb-3\">\n <span class=\"flex justify-between\">\n <span class=\"${BAR_CLASSES} w-50\" [style.animation]=\"animation\"></span>\n <span class=\"${BAR_CLASSES} w-16\" [style.animation]=\"animation\"></span>\n </span>\n <span class=\"flex justify-between\">\n <span class=\"${BAR_CLASSES} w-40\" [style.animation]=\"animation\"></span>\n <span class=\"${BAR_CLASSES} w-16\" [style.animation]=\"animation\"></span>\n </span>\n </div>\n <div asyncEmpty class=\"text-label px-2.5 pt-1 pb-2.5 text-pretty text-(--muted-foreground) empty:hidden\">\n <ng-content select=\"[resultGroupMessage]\" />\n </div>\n <ng-content />\n </ui-async>\n `,\n host: {\n class: 'block',\n role: 'group',\n '[attr.aria-label]': 'name()',\n },\n})\nexport class UiResultGroup {\n readonly label = input.required<string>();\n readonly hint = input<string>();\n readonly state = input<AsyncState>('ready');\n readonly errorMessage = input<string>();\n readonly retryLabel = input<string>();\n readonly retry = output<void>();\n\n protected readonly name = computed(() => (this.hint() ? `${this.label()}, ${this.hint()}` : this.label()));\n protected readonly animation = PULSE_ANIMATION;\n}\n"],"mappings":";;;AAIA,MAAM,kBAAkB;AAExB,MAAM,cAAc;AAqDpB,IAAa,gBAAb,MAAa,cAAa;CACf,QAAQ,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAChC,OAAO,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,QAAQ,MAAkB,SAAQ,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAClC,eAAe,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,QAAQ,OAAM;CAEJ,OAAO,eAAgB,KAAK,KAAI,IAAK,GAAG,KAAK,MAAK,EAAE,IAAK,KAAK,KAAI,MAAO,KAAK,MAAK,GAAI,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACvF,YAAY;CATpB,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAa,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAb,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAa,cAAA;EAAA,UAAA;EAAA,QAAA;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,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA,EAAA,OAAA,QAAA;EAAA,MAAA;GAAA,YAAA,EAAA,QAAA,QAAA;GAAA,YAAA,EAAA,mBAAA,SAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;EAAA,UAAA;EAAA,UAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MAtCd;GAAO,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;GAAA,SAAA,CAAA,OAAA;EAAA,CAAA;CAAA,CAAA;;AAsCN,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAa,YAAA,CAAA;EAxCzB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS,CAAC,OAAO;GACjB,UAAU;;;;;;;;;;;;;;;;;yBAiBa,YAAW;yBACX,YAAW;;;yBAGX,YAAW;yBACX,YAAW;;;;;;;;;GASlC,MAAM;IACJ,OAAO;IACP,MAAM;IACN,qBAAqB;GACtB;EACF,CAAA"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-result-group.mjs","names":[],"sources":["../../../projects/ui/result-group/result-group.ts"],"sourcesContent":["import { Component, computed, input, output } from '@angular/core';\n\nimport { type AsyncState, UiAsync } from '@joanroucoux/cairn-ui/async';\n\nconst PULSE_ANIMATION = 'cairn-pulse var(--pulse-duration) var(--ease-out) infinite alternate';\n\nconst BAR_CLASSES = 'block h-4 rounded-control bg-(--muted)';\n\n/**\n * One source of a search: a two-tone heading, then its rows, or a skeleton while it answers, a\n * message when it has nothing, or an inline error with a retry.\n *\n * @example\n * <ui-result-group label=\"Yahoo Finance\" hint=\"live prices\" [state]=\"state()\"\n * errorMessage=\"Yahoo Finance didn’t respond.\" retryLabel=\"Try again\" (retry)=\"search()\">\n * <button ui-row size=\"dense\" type=\"button\">...</button>\n * <span resultGroupMessage>No results from Yahoo Finance.</span>\n * </ui-result-group>\n */\n@Component({\n selector: 'ui-result-group',\n imports: [UiAsync],\n template: `\n <div class=\"text-caption flex items-baseline gap-1.5 pt-3 pr-2.5 pb-1 pl-2.5 tracking-(--tracking-caption)\">\n <span class=\"font-semibold text-(--foreground)\">{{ label() }}</span>\n @if (hint()) {\n <span class=\"text-(--subtle-foreground)\">{{ hint() }}</span>\n }\n </div>\n <ui-async\n variant=\"inline\"\n [errorMessage]=\"errorMessage()\"\n [retryIcon]=\"false\"\n [retryLabel]=\"retryLabel()\"\n [state]=\"state()\"\n (retry)=\"retry.emit()\"\n >\n <div asyncLoading class=\"flex flex-col gap-3.5 px-2.5 pt-2.5 pb-3\">\n <span class=\"flex justify-between\">\n <span class=\"${BAR_CLASSES} w-50\" [style.animation]=\"animation\"></span>\n <span class=\"${BAR_CLASSES} w-16\" [style.animation]=\"animation\"></span>\n </span>\n <span class=\"flex justify-between\">\n <span class=\"${BAR_CLASSES} w-40\" [style.animation]=\"animation\"></span>\n <span class=\"${BAR_CLASSES} w-16\" [style.animation]=\"animation\"></span>\n </span>\n </div>\n <div asyncEmpty class=\"text-label px-2.5 pt-1 pb-2.5 text-pretty text-(--muted-foreground) empty:hidden\">\n <ng-content select=\"[resultGroupMessage]\" />\n </div>\n <ng-content />\n </ui-async>\n `,\n host: {\n class: 'block',\n role: 'group',\n '[attr.aria-label]': 'name()',\n },\n})\nexport class UiResultGroup {\n readonly label = input.required<string>();\n readonly hint = input<string>();\n readonly state = input<AsyncState>('ready');\n readonly errorMessage = input<string>();\n readonly retryLabel = input<string>();\n readonly retry = output<void>();\n\n protected readonly name = computed(() => (this.hint() ? `${this.label()}, ${this.hint()}` : this.label()));\n protected readonly animation = PULSE_ANIMATION;\n}\n"],"mappings":";;;AAIA,MAAM,kBAAkB;AAExB,MAAM,cAAc;AAqDpB,IAAa,gBAAb,MAAa,cAAa;CACf,QAAQ,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAChC,OAAO,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,QAAQ,MAAkB,SAAQ,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAClC,eAAe,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,QAAQ,OAAM;CAEJ,OAAO,eAAgB,KAAK,KAAI,IAAK,GAAG,KAAK,MAAK,EAAE,IAAK,KAAK,KAAI,MAAO,KAAK,MAAK,GAAI,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACvF,YAAY;CATpB,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAa,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAb,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAa,cAAA;EAAA,UAAA;EAAA,QAAA;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,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA,EAAA,OAAA,QAAA;EAAA,MAAA;GAAA,YAAA,EAAA,QAAA,QAAA;GAAA,YAAA,EAAA,mBAAA,SAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;EAAA,UAAA;EAAA,UAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MAtCd;GAAO,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;GAAA,SAAA,CAAA,OAAA;EAAA,CAAA;CAAA,CAAA;;AAsCN,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAa,YAAA,CAAA;EAxCzB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS,CAAC,OAAO;GACjB,UAAU;;;;;;;;;;;;;;;;;yBAiBa,YAAW;yBACX,YAAW;;;yBAGX,YAAW;yBACX,YAAW;;;;;;;;;GASlC,MAAM;IACJ,OAAO;IACP,MAAM;IACN,qBAAqB;GACtB;EACF,CAAA"}
@@ -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\">Saisir à la main</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 '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 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-stale-link.mjs","names":[],"sources":["../../../projects/ui/stale-link/stale-link.ts"],"sourcesContent":["import { Directive, booleanAttribute, computed, input } from '@angular/core';\n\n/** Available stale link sizes. */\nexport const STALE_LINK_SIZES = ['caption', 'label'] as const;\nexport type StaleLinkSize = (typeof STALE_LINK_SIZES)[number];\n\nconst BASE_CLASSES =\n \"relative inline-flex items-center gap-1 pointer-fine:gap-0.5 rounded-[4px] font-medium text-(--stale) hover:underline underline-offset-3 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring) before:absolute before:inset-x-0 before:top-1/2 before:h-11 pointer-fine:before:h-10 before:-translate-y-1/2 before:content-['']\";\n\nconst SIZE_CLASSES: Record<StaleLinkSize, string> = {\n caption: 'text-caption',\n label: 'text-label',\n};\n\nconst CHEVRON_CLASSES =\n \"after:size-4 after:flex-none after:bg-current after:content-[''] after:mask-center after:mask-no-repeat after:mask-[url(data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.75%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27m9%2018%206-6-6-6%27%2F%3E%3C%2Fsvg%3E)]\";\n\n/**\n * Link in the stale tone, for a caption about data that is late or left out of a total, such as\n * \"1 ligne sans cours, non comptée\". `chevron` adds a trailing chevron, `size` is `caption` (the\n * default) or `label`.\n *\n * @example\n * <a uiStaleLink chevron size=\"label\" routerLink=\"/holdings\">1 cours en retard</a>\n */\n@Directive({\n selector: 'a[uiStaleLink]',\n host: { '[class]': 'classes()' },\n})\nexport class UiStaleLink {\n readonly chevron = input(false, { transform: booleanAttribute });\n readonly size = input<StaleLinkSize>('caption');\n\n protected readonly classes = computed(\n () => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}${this.chevron() ? ` ${CHEVRON_CLASSES}` : ''}`,\n );\n}\n"],"mappings":";;AAGA,MAAa,mBAAmB,CAAC,WAAW,OAAO;AAGnD,MAAM,eACJ;AAEF,MAAM,eAA8C;CAClD,SAAS;CACT,OAAO;AACR;AAED,MAAM,kBACJ;AAcF,IAAa,cAAb,MAAa,YAAW;CACb,UAAU,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,UAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CACpD,OAAO,MAAqB,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAE5B,UAAU,eACrB,GAAG,aAAY,GAAI,aAAa,KAAK,KAAI,KAAM,KAAK,QAAO,IAAK,IAAI,oBAAoB,MAC/F,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CANU,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAW,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAX,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAW,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;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,MAAA,EAAA,YAAA,EAAA,SAAA,YAAA,EAAA;EAAA,UAAA;CAAA,CAAA;;AAAX,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAW,YAAA,CAAA;EAJvB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM,EAAE,WAAW,YAAW;EAC/B,CAAA"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-stale-link.mjs","names":[],"sources":["../../../projects/ui/stale-link/stale-link.ts"],"sourcesContent":["import { Directive, booleanAttribute, computed, input } from '@angular/core';\n\n/** Available stale link sizes. */\nexport const STALE_LINK_SIZES = ['caption', 'label'] as const;\nexport type StaleLinkSize = (typeof STALE_LINK_SIZES)[number];\n\nconst BASE_CLASSES =\n \"relative inline-flex items-center gap-1 pointer-fine:gap-0.5 rounded-[4px] font-medium text-(--stale) hover:underline underline-offset-3 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring) before:absolute before:inset-x-0 before:top-1/2 before:h-11 pointer-fine:before:h-10 before:-translate-y-1/2 before:content-['']\";\n\nconst SIZE_CLASSES: Record<StaleLinkSize, string> = {\n caption: 'text-caption',\n label: 'text-label',\n};\n\nconst CHEVRON_CLASSES =\n \"after:size-4 after:flex-none after:bg-current after:content-[''] after:mask-center after:mask-no-repeat after:mask-[url(data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27black%27%20stroke-width%3D%271.75%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27m9%2018%206-6-6-6%27%2F%3E%3C%2Fsvg%3E)]\";\n\n/**\n * Link in the stale tone, for a caption about data that is late or left out of a total, such as\n * \"1 holding without a price, not counted\". `chevron` adds a trailing chevron, `size` is `caption` (the\n * default) or `label`.\n *\n * @example\n * <a uiStaleLink chevron size=\"label\" routerLink=\"/holdings\">1 stale price</a>\n */\n@Directive({\n selector: 'a[uiStaleLink]',\n host: { '[class]': 'classes()' },\n})\nexport class UiStaleLink {\n readonly chevron = input(false, { transform: booleanAttribute });\n readonly size = input<StaleLinkSize>('caption');\n\n protected readonly classes = computed(\n () => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}${this.chevron() ? ` ${CHEVRON_CLASSES}` : ''}`,\n );\n}\n"],"mappings":";;AAGA,MAAa,mBAAmB,CAAC,WAAW,OAAO;AAGnD,MAAM,eACJ;AAEF,MAAM,eAA8C;CAClD,SAAS;CACT,OAAO;AACR;AAED,MAAM,kBACJ;AAcF,IAAa,cAAb,MAAa,YAAW;CACb,UAAU,MAAM,OAAK;EAAA,GAAA,YAAA,EAAA,WAAA,UAAA,+BAAA,CAAA;EAAI,WAAW;CAAgB,CAAA;CACpD,OAAO,MAAqB,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAE5B,UAAU,eACrB,GAAG,aAAY,GAAI,aAAa,KAAK,KAAI,KAAM,KAAK,QAAO,IAAK,IAAI,oBAAoB,MAC/F,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CANU,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAW,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAX,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAW,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;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,MAAA,EAAA,YAAA,EAAA,SAAA,YAAA,EAAA;EAAA,UAAA;CAAA,CAAA;;AAAX,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAW,YAAA,CAAA;EAJvB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM,EAAE,WAAW,YAAW;EAC/B,CAAA"}
@@ -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/** Body cell. Same inputs as `UiTh` bar `tall` and `width`, which must be set on both to match. */\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 * line. Other controls in the row need `uiRowAction` to stay clickable.\n *\n * @example\n * <td uiTd primary><a uiRowLink href=\"/lines/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/** A control in another cell of a stretched-link row: keeps it clickable above the row-wide link. */\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 € · cost 388.10 €</span>\n * <span uiCellSub tone=\"stale\">Quote 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 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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"}
@@ -11,7 +11,7 @@ var UiToasts = class UiToasts {
11
11
  kind: "success"
12
12
  });
13
13
  }
14
- showError(message, closeLabel = "Fermer") {
14
+ showError(message, closeLabel = "Close") {
15
15
  this.current.set({
16
16
  id: ++this.sequence,
17
17
  text: message,
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-toast.mjs","names":[],"sources":["../../../projects/ui/toast/toasts.ts","../../../projects/ui/toast/toast.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\n\nexport type Toast =\n | { readonly id: number; readonly text: string; readonly kind: 'success' }\n | { readonly id: number; readonly text: string; readonly kind: 'error'; readonly closeLabel: string };\n\n/**\n * One-slot message queue read by `ui-toaster`: a confirmation that times out, or an error that stays until closed.\n *\n * @example\n * inject(UiToasts).show('Achat enregistré');\n * inject(UiToasts).showError(\"Échec de l'import\");\n */\n@Injectable({ providedIn: 'root' })\nexport class UiToasts {\n private readonly current = signal<Toast | null>(null);\n private sequence = 0;\n\n readonly toast = this.current.asReadonly();\n\n show(message: string): void {\n this.current.set({ id: ++this.sequence, text: message, kind: 'success' });\n }\n\n showError(message: string, closeLabel = 'Fermer'): void {\n this.current.set({ id: ++this.sequence, text: message, kind: 'error', closeLabel });\n }\n\n dismiss(): void {\n this.current.set(null);\n }\n}\n","import { Component, DestroyRef, ElementRef, afterNextRender, effect, inject, signal, untracked } from '@angular/core';\n\nimport { UiToasts } from './toasts';\n\nconst DEFAULT_DURATION = 5000;\n\nconst TOAST_CLASSES =\n 'pointer-events-auto flex min-h-11 min-w-[min(280px,calc(100vw-2rem))] max-w-[min(400px,calc(100vw-2rem))] items-center gap-2.5 rounded-container bg-(--primary) px-4 py-3 text-label font-medium text-(--primary-foreground) shadow-[0_8px_24px_rgb(0_0_0/0.16)] transition-[opacity,translate] duration-(--duration-base) ease-out starting:opacity-0 starting:translate-y-2 motion-reduce:starting:translate-y-0';\n\nconst CLOSE_CLASSES =\n 'relative grid size-7 flex-none cursor-pointer place-items-center -my-1 -mr-2 rounded-[calc(var(--radius-control)-2px)] text-(--primary-foreground) outline-none hover:bg-[rgb(127_127_127/0.2)] focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-(--primary-foreground) after:absolute after:-inset-2 pointer-fine:after:-inset-1';\n\nconst readDuration = (host: HTMLElement): number => {\n const raw = getComputedStyle(host).getPropertyValue('--toast-duration').trim();\n const value = parseFloat(raw);\n\n if (Number.isNaN(value)) {\n return DEFAULT_DURATION;\n }\n\n return raw.endsWith('ms') ? value : value * 1000;\n};\n\n/**\n * Message shown by `UiToasts`: one at a time, no action. A confirmation (`show`) is gone after `--toast-duration`;\n * an error (`showError`) stays until its cross is clicked. Centred at the bottom of the content area: from `64rem`\n * between `--sidebar-width` (0 when unset) and the right edge.\n * Place it once in the app shell.\n *\n * @example\n * <ui-toaster />\n */\n@Component({\n selector: 'ui-toaster',\n template: `\n @if (toasts.toast(); as toast) {\n <div\n animate.leave=\"ui-leave-fade\"\n [class]=\"toastClasses\"\n (focusin)=\"setFocused(true)\"\n (focusout)=\"setFocused(false)\"\n (mouseenter)=\"setHovered(true)\"\n (mouseleave)=\"setHovered(false)\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"block size-4 flex-none fill-none stroke-current stroke-2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n viewBox=\"0 0 24 24\"\n >\n @if (toast.kind === 'error') {\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n } @else {\n <path d=\"M20 6 9 17l-5-5\" />\n }\n </svg>\n <span class=\"min-w-0 flex-1 text-pretty\">{{ toast.text }}</span>\n @if (toast.kind === 'error') {\n <button type=\"button\" [attr.aria-label]=\"toast.closeLabel\" [class]=\"closeClasses\" (click)=\"toasts.dismiss()\">\n <svg\n aria-hidden=\"true\"\n class=\"block size-4 flex-none fill-none stroke-current stroke-2\"\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 `,\n host: {\n role: 'status',\n popover: 'manual',\n class:\n 'pointer-events-none fixed inset-x-0 top-auto m-0 flex h-auto w-auto justify-center overflow-visible border-0 bg-transparent p-0 bottom-[calc(var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))+var(--action-bar-height,0px)+8px)] lg:left-[var(--sidebar-width,0px)] lg:bottom-6',\n },\n})\nexport class UiToaster {\n protected readonly toasts = inject(UiToasts);\n protected readonly toastClasses = TOAST_CLASSES;\n protected readonly closeClasses = CLOSE_CLASSES;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly hovered = signal(false);\n private popoverShown = false;\n private readonly focused = signal(false);\n private lastId = 0;\n private raisedId = 0;\n private remaining = DEFAULT_DURATION;\n private startedAt = 0;\n private timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor() {\n effect(() => {\n const toast = this.toasts.toast();\n const paused = this.hovered() || this.focused();\n\n untracked(() => {\n if (!toast) {\n this.stop();\n this.hovered.set(false);\n this.focused.set(false);\n return;\n }\n\n if (toast.id !== this.raisedId) {\n this.raisedId = toast.id;\n this.raise();\n }\n this.host.querySelectorAll('.ui-leave-fade').forEach((leaving) => leaving.remove());\n\n if (toast.kind === 'error') {\n this.stop();\n } else if (paused) {\n this.pause();\n } else {\n this.resume(toast.id);\n }\n });\n });\n\n afterNextRender(() => {\n this.host.showPopover();\n this.popoverShown = true;\n });\n\n inject(DestroyRef).onDestroy(() => {\n this.stop();\n });\n }\n\n protected setHovered(value: boolean): void {\n this.hovered.set(value);\n }\n\n protected setFocused(value: boolean): void {\n this.focused.set(value);\n }\n\n private raise(): void {\n if (this.popoverShown) {\n this.host.hidePopover();\n this.host.showPopover();\n }\n }\n\n private resume(id: number): void {\n if (id !== this.lastId) {\n this.lastId = id;\n this.remaining = readDuration(this.host);\n }\n\n clearTimeout(this.timer);\n this.startedAt = Date.now();\n this.timer = setTimeout(() => this.toasts.dismiss(), this.remaining);\n }\n\n private pause(): void {\n if (this.timer !== undefined) {\n this.remaining -= Date.now() - this.startedAt;\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n\n private stop(): void {\n clearTimeout(this.timer);\n this.timer = undefined;\n this.lastId = 0;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-toast.mjs","names":[],"sources":["../../../projects/ui/toast/toasts.ts","../../../projects/ui/toast/toast.ts"],"sourcesContent":["import { Injectable, signal } from '@angular/core';\n\nexport type Toast =\n | { readonly id: number; readonly text: string; readonly kind: 'success' }\n | { readonly id: number; readonly text: string; readonly kind: 'error'; readonly closeLabel: string };\n\n/**\n * One-slot message queue read by `ui-toaster`: a confirmation that times out, or an error that stays until closed.\n *\n * @example\n * inject(UiToasts).show('Purchase recorded');\n * inject(UiToasts).showError('Import failed');\n */\n@Injectable({ providedIn: 'root' })\nexport class UiToasts {\n private readonly current = signal<Toast | null>(null);\n private sequence = 0;\n\n readonly toast = this.current.asReadonly();\n\n show(message: string): void {\n this.current.set({ id: ++this.sequence, text: message, kind: 'success' });\n }\n\n showError(message: string, closeLabel = 'Close'): void {\n this.current.set({ id: ++this.sequence, text: message, kind: 'error', closeLabel });\n }\n\n dismiss(): void {\n this.current.set(null);\n }\n}\n","import { Component, DestroyRef, ElementRef, afterNextRender, effect, inject, signal, untracked } from '@angular/core';\n\nimport { UiToasts } from './toasts';\n\nconst DEFAULT_DURATION = 5000;\n\nconst TOAST_CLASSES =\n 'pointer-events-auto flex min-h-11 min-w-[min(280px,calc(100vw-2rem))] max-w-[min(400px,calc(100vw-2rem))] items-center gap-2.5 rounded-container bg-(--primary) px-4 py-3 text-label font-medium text-(--primary-foreground) shadow-[0_8px_24px_rgb(0_0_0/0.16)] transition-[opacity,translate] duration-(--duration-base) ease-out starting:opacity-0 starting:translate-y-2 motion-reduce:starting:translate-y-0';\n\nconst CLOSE_CLASSES =\n 'relative grid size-7 flex-none cursor-pointer place-items-center -my-1 -mr-2 rounded-[calc(var(--radius-control)-2px)] text-(--primary-foreground) outline-none hover:bg-[rgb(127_127_127/0.2)] focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-(--primary-foreground) after:absolute after:-inset-2 pointer-fine:after:-inset-1';\n\nconst readDuration = (host: HTMLElement): number => {\n const raw = getComputedStyle(host).getPropertyValue('--toast-duration').trim();\n const value = parseFloat(raw);\n\n if (Number.isNaN(value)) {\n return DEFAULT_DURATION;\n }\n\n return raw.endsWith('ms') ? value : value * 1000;\n};\n\n/**\n * Message shown by `UiToasts`: one at a time, no action. A confirmation (`show`) is gone after `--toast-duration`;\n * an error (`showError`) stays until its cross is clicked. Centered at the bottom of the content area: from `64rem`\n * between `--sidebar-width` (0 when unset) and the right edge.\n * Place it once in the app shell.\n *\n * @example\n * <ui-toaster />\n */\n@Component({\n selector: 'ui-toaster',\n template: `\n @if (toasts.toast(); as toast) {\n <div\n animate.leave=\"ui-leave-fade\"\n [class]=\"toastClasses\"\n (focusin)=\"setFocused(true)\"\n (focusout)=\"setFocused(false)\"\n (mouseenter)=\"setHovered(true)\"\n (mouseleave)=\"setHovered(false)\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"block size-4 flex-none fill-none stroke-current stroke-2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n viewBox=\"0 0 24 24\"\n >\n @if (toast.kind === 'error') {\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n } @else {\n <path d=\"M20 6 9 17l-5-5\" />\n }\n </svg>\n <span class=\"min-w-0 flex-1 text-pretty\">{{ toast.text }}</span>\n @if (toast.kind === 'error') {\n <button type=\"button\" [attr.aria-label]=\"toast.closeLabel\" [class]=\"closeClasses\" (click)=\"toasts.dismiss()\">\n <svg\n aria-hidden=\"true\"\n class=\"block size-4 flex-none fill-none stroke-current stroke-2\"\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 `,\n host: {\n role: 'status',\n popover: 'manual',\n class:\n 'pointer-events-none fixed inset-x-0 top-auto m-0 flex h-auto w-auto justify-center overflow-visible border-0 bg-transparent p-0 bottom-[calc(var(--tab-bar-height,calc(52px+env(safe-area-inset-bottom)))+var(--action-bar-height,0px)+8px)] lg:left-[var(--sidebar-width,0px)] lg:bottom-6',\n },\n})\nexport class UiToaster {\n protected readonly toasts = inject(UiToasts);\n protected readonly toastClasses = TOAST_CLASSES;\n protected readonly closeClasses = CLOSE_CLASSES;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly hovered = signal(false);\n private popoverShown = false;\n private readonly focused = signal(false);\n private lastId = 0;\n private raisedId = 0;\n private remaining = DEFAULT_DURATION;\n private startedAt = 0;\n private timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor() {\n effect(() => {\n const toast = this.toasts.toast();\n const paused = this.hovered() || this.focused();\n\n untracked(() => {\n if (!toast) {\n this.stop();\n this.hovered.set(false);\n this.focused.set(false);\n return;\n }\n\n if (toast.id !== this.raisedId) {\n this.raisedId = toast.id;\n this.raise();\n }\n this.host.querySelectorAll('.ui-leave-fade').forEach((leaving) => leaving.remove());\n\n if (toast.kind === 'error') {\n this.stop();\n } else if (paused) {\n this.pause();\n } else {\n this.resume(toast.id);\n }\n });\n });\n\n afterNextRender(() => {\n this.host.showPopover();\n this.popoverShown = true;\n });\n\n inject(DestroyRef).onDestroy(() => {\n this.stop();\n });\n }\n\n protected setHovered(value: boolean): void {\n this.hovered.set(value);\n }\n\n protected setFocused(value: boolean): void {\n this.focused.set(value);\n }\n\n private raise(): void {\n if (this.popoverShown) {\n this.host.hidePopover();\n this.host.showPopover();\n }\n }\n\n private resume(id: number): void {\n if (id !== this.lastId) {\n this.lastId = id;\n this.remaining = readDuration(this.host);\n }\n\n clearTimeout(this.timer);\n this.startedAt = Date.now();\n this.timer = setTimeout(() => this.toasts.dismiss(), this.remaining);\n }\n\n private pause(): void {\n if (this.timer !== undefined) {\n this.remaining -= Date.now() - this.startedAt;\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n\n private stop(): void {\n clearTimeout(this.timer);\n this.timer = undefined;\n this.lastId = 0;\n }\n}\n"],"mappings":"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"}