@joanroucoux/cairn-ui 0.8.2 → 0.9.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 (124) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs +57 -53
  3. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs.map +1 -1
  4. package/fesm2022/joanroucoux-cairn-ui-alert.mjs +155 -47
  5. package/fesm2022/joanroucoux-cairn-ui-alert.mjs.map +1 -1
  6. package/fesm2022/joanroucoux-cairn-ui-amount.mjs +220 -110
  7. package/fesm2022/joanroucoux-cairn-ui-amount.mjs.map +1 -1
  8. package/fesm2022/joanroucoux-cairn-ui-async.mjs +392 -216
  9. package/fesm2022/joanroucoux-cairn-ui-async.mjs.map +1 -1
  10. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs +145 -68
  11. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs.map +1 -1
  12. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs +87 -47
  13. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs.map +1 -1
  14. package/fesm2022/joanroucoux-cairn-ui-badge.mjs +83 -43
  15. package/fesm2022/joanroucoux-cairn-ui-badge.mjs.map +1 -1
  16. package/fesm2022/joanroucoux-cairn-ui-button.mjs +184 -104
  17. package/fesm2022/joanroucoux-cairn-ui-button.mjs.map +1 -1
  18. package/fesm2022/joanroucoux-cairn-ui-card.mjs +232 -137
  19. package/fesm2022/joanroucoux-cairn-ui-card.mjs.map +1 -1
  20. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs +298 -102
  21. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs.map +1 -1
  22. package/fesm2022/joanroucoux-cairn-ui-control.mjs +4 -17
  23. package/fesm2022/joanroucoux-cairn-ui-control.mjs.map +1 -1
  24. package/fesm2022/joanroucoux-cairn-ui-delta.mjs +150 -83
  25. package/fesm2022/joanroucoux-cairn-ui-delta.mjs.map +1 -1
  26. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs +508 -471
  27. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs.map +1 -1
  28. package/fesm2022/joanroucoux-cairn-ui-donut.mjs +255 -157
  29. package/fesm2022/joanroucoux-cairn-ui-donut.mjs.map +1 -1
  30. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs +303 -0
  31. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs.map +1 -0
  32. package/fesm2022/joanroucoux-cairn-ui-empty.mjs +76 -35
  33. package/fesm2022/joanroucoux-cairn-ui-empty.mjs.map +1 -1
  34. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs +40 -31
  35. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs.map +1 -1
  36. package/fesm2022/joanroucoux-cairn-ui-fact.mjs +188 -79
  37. package/fesm2022/joanroucoux-cairn-ui-fact.mjs.map +1 -1
  38. package/fesm2022/joanroucoux-cairn-ui-field.mjs +309 -173
  39. package/fesm2022/joanroucoux-cairn-ui-field.mjs.map +1 -1
  40. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs +165 -87
  41. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs.map +1 -1
  42. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs +269 -0
  43. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs.map +1 -0
  44. package/fesm2022/joanroucoux-cairn-ui-input.mjs +205 -85
  45. package/fesm2022/joanroucoux-cairn-ui-input.mjs.map +1 -1
  46. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs +838 -512
  47. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs.map +1 -1
  48. package/fesm2022/joanroucoux-cairn-ui-menu.mjs +401 -225
  49. package/fesm2022/joanroucoux-cairn-ui-menu.mjs.map +1 -1
  50. package/fesm2022/joanroucoux-cairn-ui-meter.mjs +143 -57
  51. package/fesm2022/joanroucoux-cairn-ui-meter.mjs.map +1 -1
  52. package/fesm2022/joanroucoux-cairn-ui-motion.mjs +367 -399
  53. package/fesm2022/joanroucoux-cairn-ui-motion.mjs.map +1 -1
  54. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs +73 -44
  55. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs.map +1 -1
  56. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs +191 -0
  57. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs.map +1 -0
  58. package/fesm2022/joanroucoux-cairn-ui-row.mjs +408 -146
  59. package/fesm2022/joanroucoux-cairn-ui-row.mjs.map +1 -1
  60. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs +183 -81
  61. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs.map +1 -1
  62. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs +270 -0
  63. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs.map +1 -0
  64. package/fesm2022/joanroucoux-cairn-ui-select.mjs +121 -67
  65. package/fesm2022/joanroucoux-cairn-ui-select.mjs.map +1 -1
  66. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs +129 -51
  67. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs.map +1 -1
  68. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs +80 -39
  69. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs.map +1 -1
  70. package/fesm2022/joanroucoux-cairn-ui-stat.mjs +85 -55
  71. package/fesm2022/joanroucoux-cairn-ui-stat.mjs.map +1 -1
  72. package/fesm2022/joanroucoux-cairn-ui-switch.mjs +48 -35
  73. package/fesm2022/joanroucoux-cairn-ui-switch.mjs.map +1 -1
  74. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs +113 -69
  75. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs.map +1 -1
  76. package/fesm2022/joanroucoux-cairn-ui-table.mjs +1036 -310
  77. package/fesm2022/joanroucoux-cairn-ui-table.mjs.map +1 -1
  78. package/fesm2022/joanroucoux-cairn-ui-toast.mjs +240 -127
  79. package/fesm2022/joanroucoux-cairn-ui-toast.mjs.map +1 -1
  80. package/fesm2022/joanroucoux-cairn-ui.mjs +0 -4
  81. package/package.json +17 -1
  82. package/styles/motion.css +1 -13
  83. package/styles/tokens.css +35 -64
  84. package/types/joanroucoux-cairn-ui-action-bar.d.ts +9 -14
  85. package/types/joanroucoux-cairn-ui-alert.d.ts +29 -15
  86. package/types/joanroucoux-cairn-ui-amount.d.ts +64 -32
  87. package/types/joanroucoux-cairn-ui-async.d.ts +85 -38
  88. package/types/joanroucoux-cairn-ui-avatar.d.ts +34 -22
  89. package/types/joanroucoux-cairn-ui-back-link.d.ts +20 -15
  90. package/types/joanroucoux-cairn-ui-badge.d.ts +22 -14
  91. package/types/joanroucoux-cairn-ui-button.d.ts +36 -18
  92. package/types/joanroucoux-cairn-ui-card.d.ts +48 -23
  93. package/types/joanroucoux-cairn-ui-choice-chips.d.ts +91 -35
  94. package/types/joanroucoux-cairn-ui-control.d.ts +9 -18
  95. package/types/joanroucoux-cairn-ui-delta.d.ts +46 -24
  96. package/types/joanroucoux-cairn-ui-dialog.d.ts +124 -57
  97. package/types/joanroucoux-cairn-ui-donut.d.ts +83 -46
  98. package/types/joanroucoux-cairn-ui-drawer.d.ts +73 -0
  99. package/types/joanroucoux-cairn-ui-empty.d.ts +20 -13
  100. package/types/joanroucoux-cairn-ui-external-link.d.ts +6 -10
  101. package/types/joanroucoux-cairn-ui-fact.d.ts +49 -25
  102. package/types/joanroucoux-cairn-ui-field.d.ts +72 -49
  103. package/types/joanroucoux-cairn-ui-filter-chips.d.ts +35 -20
  104. package/types/joanroucoux-cairn-ui-group-header.d.ts +58 -0
  105. package/types/joanroucoux-cairn-ui-input.d.ts +59 -37
  106. package/types/joanroucoux-cairn-ui-line-chart.d.ts +199 -89
  107. package/types/joanroucoux-cairn-ui-menu.d.ts +81 -44
  108. package/types/joanroucoux-cairn-ui-meter.d.ts +44 -22
  109. package/types/joanroucoux-cairn-ui-motion.d.ts +61 -75
  110. package/types/joanroucoux-cairn-ui-nav-item.d.ts +15 -13
  111. package/types/joanroucoux-cairn-ui-result-group.d.ts +52 -0
  112. package/types/joanroucoux-cairn-ui-row.d.ts +92 -37
  113. package/types/joanroucoux-cairn-ui-segmented.d.ts +51 -27
  114. package/types/joanroucoux-cairn-ui-select-pill.d.ts +59 -0
  115. package/types/joanroucoux-cairn-ui-select.d.ts +28 -18
  116. package/types/joanroucoux-cairn-ui-skeleton.d.ts +35 -18
  117. package/types/joanroucoux-cairn-ui-stale-link.d.ts +23 -16
  118. package/types/joanroucoux-cairn-ui-stat.d.ts +26 -21
  119. package/types/joanroucoux-cairn-ui-switch.d.ts +7 -11
  120. package/types/joanroucoux-cairn-ui-tab-bar.d.ts +20 -17
  121. package/types/joanroucoux-cairn-ui-table.d.ts +251 -89
  122. package/types/joanroucoux-cairn-ui-toast.d.ts +46 -36
  123. package/types/joanroucoux-cairn-ui.d.ts +1 -2
  124. package/fesm2022/joanroucoux-cairn-ui.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-async.mjs","sources":["../../../projects/ui/async/delayed-state.ts","../../../projects/ui/async/async.ts","../../../projects/ui/async/joanroucoux-cairn-ui-async.ts"],"sourcesContent":["import { DestroyRef, type Signal, effect, inject, signal, untracked } from '@angular/core';\n\nimport type { AsyncState } from './async';\n\nexport const SKELETON_DELAY_MS = 150;\nexport const SKELETON_MIN_MS = 400;\n\n/**\n * Turns the live state of a call into the state to draw: `loading` only appears once the call has\n * lasted 150 ms and, once shown, stays at least 400 ms, so a fast call never flashes a skeleton and a\n * slow one never blinks. Until then the previous state stays on screen (a reload keeps its content);\n * `null` means nothing to draw yet, for a first load still under 150 ms. Call it in an injection context.\n *\n * @example\n * protected readonly shown = delayedState(this.state);\n */\nexport function delayedState(source: Signal<AsyncState>): Signal<AsyncState | null> {\n const displayed = signal<AsyncState | null>(null);\n let timer: ReturnType<typeof setTimeout> | undefined;\n let shownAt = 0;\n\n const clear = (): void => {\n clearTimeout(timer);\n timer = undefined;\n };\n\n inject(DestroyRef).onDestroy(clear);\n\n effect(() => {\n const state = source();\n\n untracked(() => {\n if (state === 'loading') {\n if (displayed() === 'loading') {\n clear();\n } else {\n timer = setTimeout(() => {\n timer = undefined;\n shownAt = Date.now();\n displayed.set('loading');\n }, SKELETON_DELAY_MS);\n }\n\n return;\n }\n\n clear();\n\n const remaining = shownAt + SKELETON_MIN_MS - Date.now();\n\n if (displayed() === 'loading' && remaining > 0) {\n timer = setTimeout(() => {\n timer = undefined;\n displayed.set(untracked(source));\n }, remaining);\n } else {\n displayed.set(state);\n }\n });\n });\n\n return displayed.asReadonly();\n}\n","import { Component, booleanAttribute, computed, input, output } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\nimport { delayedState } from './delayed-state';\n\n/** Available async block states. `AsyncState` is derived from this tuple. */\nexport const ASYNC_STATES = ['loading', 'error', 'empty', 'ready'] as const;\nexport type AsyncState = (typeof ASYNC_STATES)[number];\n\n/** Looks of the error block. `AsyncVariant` is derived from this tuple. */\nexport const ASYNC_VARIANTS = ['elevated', 'plain', 'emphasis', 'inline'] as const;\nexport type AsyncVariant = (typeof ASYNC_VARIANTS)[number];\n\n/** Alignments of the error block; `auto` is centred from 64rem. `AsyncAlign` is derived from this tuple. */\nexport const ASYNC_ALIGNS = ['start', 'center', 'auto'] as const;\nexport type AsyncAlign = (typeof ASYNC_ALIGNS)[number];\n\nconst RETRY_BASE_CLASSES =\n 'relative inline-flex items-center justify-center rounded-control font-medium whitespace-nowrap cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring) text-label';\n\nconst RETRY_OUTLINE_CLASSES =\n 'bg-(--card) text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)] hover:bg-(--glow)';\n\nconst RETRY_PRIMARY_CLASSES = 'bg-(--primary) text-(--primary-foreground) hover:bg-(--primary-to)';\n\nconst RETRY_BLOCK_CLASSES = 'min-h-(--row-min) gap-2 pl-3 pr-4';\n\nconst RETRY_INLINE_CLASSES = 'h-11 pointer-fine:h-8 flex-none gap-1.5 pl-2.5 pr-3';\n\nconst ELEVATED_SURFACE_CLASSES = 'rounded-control bg-(--elevated)';\n\nconst CARD_SURFACE_CLASSES = 'rounded-container bg-(--card) shadow-[inset_0_0_0_1px_var(--border)]';\n\ntype BlockSpec = {\n surface: string;\n gap: string;\n padding: Record<AsyncAlign, string>;\n title: string;\n message: Record<AsyncAlign, string>;\n retryMargin: Record<AsyncAlign, string>;\n retry: string;\n};\n\nconst BLOCK_SPECS: Record<Exclude<AsyncVariant, 'inline'>, BlockSpec> = {\n elevated: {\n surface: ELEVATED_SURFACE_CLASSES,\n gap: 'gap-1',\n padding: { start: 'p-4', center: 'px-4 py-10', auto: 'p-4 lg:py-10' },\n title: 'text-body font-medium',\n message: { start: 'text-label', center: 'text-label', auto: 'text-label' },\n retryMargin: { start: 'mt-2', center: 'mt-2', auto: 'mt-2' },\n retry: RETRY_OUTLINE_CLASSES,\n },\n plain: {\n surface: '',\n gap: 'gap-1',\n padding: { start: 'px-4 py-5', center: 'px-4 py-12', auto: 'px-4 py-5 lg:py-12' },\n title: 'text-body leading-[normal] font-medium',\n message: {\n start: 'text-label leading-[normal]',\n center: 'text-label leading-[normal]',\n auto: 'text-label leading-[normal]',\n },\n retryMargin: { start: 'mt-2', center: 'mt-2', auto: 'mt-2' },\n retry: RETRY_OUTLINE_CLASSES,\n },\n emphasis: {\n surface: '',\n gap: 'gap-3',\n padding: { start: 'px-4 py-6', center: 'px-4 py-14', auto: 'px-4 py-6 lg:py-14' },\n title: 'text-title font-semibold',\n message: {\n start: 'text-label',\n center: 'text-body leading-[normal]',\n auto: 'text-label lg:text-body lg:leading-[normal]',\n },\n retryMargin: { start: 'mt-1', center: 'mt-2', auto: 'mt-1 lg:mt-2' },\n retry: RETRY_PRIMARY_CLASSES,\n },\n};\n\nconst ALIGN_CLASSES: Record<AsyncAlign, string> = {\n start: 'items-start',\n center: 'items-center text-center',\n auto: 'items-start lg:items-center lg:text-center',\n};\n\nconst INLINE_BOX_CLASSES = 'flex-row items-center justify-between gap-3 pt-1.5 pr-1.5 pb-2 pl-2.5';\n\n/**\n * The three states of a block that depends on a service call, next to the ready content.\n *\n * @example\n * <ui-async [state]=\"totalState()\" errorTitle=\"Total could not be loaded\" errorMessage=\"The server did not answer.\" retryLabel=\"Retry\" (retry)=\"reload()\">\n * <span asyncLoading><ui-skeleton shape=\"figure\" /></span>\n * <span asyncEmpty>Add a holding to see your total.</span>\n * <span>{{ total() }}</span>\n * </ui-async>\n */\n@Component({\n selector: 'ui-async',\n template: `\n @switch (shown()) {\n @case (null) {}\n @case ('loading') {\n <ng-content select=\"[asyncLoading]\" />\n }\n @case ('error') {\n <div aria-live=\"polite\" role=\"alert\" [class]=\"boxClasses()\">\n @if (variant() === 'inline') {\n <span class=\"text-label text-(--muted-foreground)\">{{ errorMessage() }}</span>\n } @else {\n @if (variant() === 'emphasis') {\n <h2 [class]=\"titleClasses()\">{{ errorTitle() }}</h2>\n } @else {\n <span [class]=\"titleClasses()\">{{ errorTitle() }}</span>\n }\n <span class=\"text-(--muted-foreground)\" [class]=\"messageClasses()\">{{ errorMessage() }}</span>\n }\n <button type=\"button\" [class]=\"retryButtonClasses()\" (click)=\"retry.emit()\">\n <svg\n aria-hidden=\"true\"\n class=\"block flex-none fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n [attr.height]=\"iconSize()\"\n [attr.width]=\"iconSize()\"\n >\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n {{ retryLabel() }}\n </button>\n </div>\n }\n @case ('empty') {\n <ng-content select=\"[asyncEmpty]\" />\n }\n @default {\n <ng-content />\n }\n }\n `,\n host: {\n '[attr.aria-busy]': \"state() === 'loading' || null\",\n '[class.flex]': 'filling()',\n '[class.flex-col]': 'filling()',\n },\n})\nexport class UiAsync {\n readonly state = input.required<AsyncState>();\n readonly errorTitle = input<string>();\n readonly errorMessage = input<string>();\n readonly retryLabel = input<string>();\n readonly variant = input<AsyncVariant>('elevated');\n readonly align = input<AsyncAlign>('start');\n readonly card = input(false, { transform: booleanAttribute });\n readonly fill = input(false, { transform: booleanAttribute });\n readonly retry = output<void>();\n\n protected readonly shown = delayedState(this.state);\n\n protected readonly filling = computed(() => this.fill() && this.shown() === 'error');\n\n protected readonly iconSize = computed(() => (this.variant() === 'inline' ? 16 : 18));\n\n readonly #spec = computed(() => {\n const variant = this.variant();\n\n return variant === 'inline' ? null : BLOCK_SPECS[variant];\n });\n\n protected readonly boxClasses = computed(() => {\n const spec = this.#spec();\n const fill = this.fill() ? ' flex-1 justify-center' : '';\n\n if (spec === null) {\n return `flex ${INLINE_BOX_CLASSES}${this.card() ? ` ${CARD_SURFACE_CLASSES}` : ''}${this.fill() ? ' flex-1' : ''}`;\n }\n\n const surface = this.card() ? CARD_SURFACE_CLASSES : spec.surface;\n\n return `flex flex-col ${surface} ${spec.gap} ${ALIGN_CLASSES[this.align()]} ${spec.padding[this.align()]}${fill}`;\n });\n\n protected readonly titleClasses = computed(() => this.#spec()!.title);\n\n protected readonly messageClasses = computed(() => this.#spec()!.message[this.align()]);\n\n protected readonly retryButtonClasses = computed(() => {\n const spec = this.#spec();\n\n if (spec === null) {\n return `${RETRY_BASE_CLASSES} ${RETRY_OUTLINE_CLASSES} ${RETRY_INLINE_CLASSES}`;\n }\n\n return `${RETRY_BASE_CLASSES} ${spec.retry} ${RETRY_BLOCK_CLASSES} ${spec.retryMargin[this.align()]}`;\n });\n\n constructor() {\n holdTransitionsUntilRendered();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-async.mjs","names":[],"sources":["../../../projects/ui/async/delayed-state.ts","../../../projects/ui/async/async.ts"],"sourcesContent":["import { DestroyRef, type Signal, effect, inject, signal, untracked } from '@angular/core';\n\nimport type { AsyncState } from './async';\n\nexport const SKELETON_DELAY_MS = 150;\nexport const SKELETON_MIN_MS = 400;\n\n/**\n * Turns the live state of a call into the state to draw: `loading` only appears once the call has\n * lasted 150 ms and, once shown, stays at least 400 ms. Until then the previous state stays on\n * screen; `null` means nothing to draw yet (a first load under 150 ms). Call it in an injection context.\n *\n * @example\n * protected readonly shown = delayedState(this.state);\n */\nexport function delayedState(source: Signal<AsyncState>): Signal<AsyncState | null> {\n const displayed = signal<AsyncState | null>(null);\n let timer: ReturnType<typeof setTimeout> | undefined;\n let shownAt = 0;\n\n const clear = (): void => {\n clearTimeout(timer);\n timer = undefined;\n };\n\n inject(DestroyRef).onDestroy(clear);\n\n effect(() => {\n const state = source();\n\n untracked(() => {\n if (state === 'loading') {\n if (displayed() === 'loading') {\n clear();\n } else {\n timer = setTimeout(() => {\n timer = undefined;\n shownAt = Date.now();\n displayed.set('loading');\n }, SKELETON_DELAY_MS);\n }\n\n return;\n }\n\n clear();\n\n const remaining = shownAt + SKELETON_MIN_MS - Date.now();\n\n if (displayed() === 'loading' && remaining > 0) {\n timer = setTimeout(() => {\n timer = undefined;\n displayed.set(untracked(source));\n }, remaining);\n } else {\n displayed.set(state);\n }\n });\n });\n\n return displayed.asReadonly();\n}\n","import { Component, booleanAttribute, computed, input, output } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\nimport { delayedState } from './delayed-state';\n\n/** Available async block states. */\nexport const ASYNC_STATES = ['loading', 'error', 'empty', 'ready'] as const;\nexport type AsyncState = (typeof ASYNC_STATES)[number];\n\n/** Looks of the error block. */\nexport const ASYNC_VARIANTS = ['elevated', 'plain', 'emphasis', 'inline'] as const;\nexport type AsyncVariant = (typeof ASYNC_VARIANTS)[number];\n\n/** Alignments of the error block; `auto` is centred from 64rem. */\nexport const ASYNC_ALIGNS = ['start', 'center', 'auto'] as const;\nexport type AsyncAlign = (typeof ASYNC_ALIGNS)[number];\n\nconst RETRY_BASE_CLASSES =\n 'relative inline-flex items-center justify-center rounded-control font-medium whitespace-nowrap cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring) text-label';\n\nconst RETRY_OUTLINE_CLASSES =\n 'bg-(--card) text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)] hover:bg-(--glow)';\n\nconst RETRY_PRIMARY_CLASSES = 'bg-(--primary) text-(--primary-foreground) hover:bg-(--primary-to)';\n\nconst RETRY_BLOCK_CLASSES = 'min-h-(--row-min) gap-2 pl-3 pr-4';\n\nconst RETRY_INLINE_CLASSES = 'h-11 pointer-fine:h-8 flex-none';\n\nconst RETRY_INLINE_ICON_CLASSES = 'gap-1.5 pl-2.5 pr-3';\n\nconst RETRY_INLINE_TEXT_CLASSES = 'px-3';\n\nconst ELEVATED_SURFACE_CLASSES = 'rounded-control bg-(--elevated)';\n\nconst CARD_SURFACE_CLASSES = 'rounded-container bg-(--card) shadow-[inset_0_0_0_1px_var(--border)]';\n\ntype BlockSpec = {\n surface: string;\n gap: string;\n padding: Record<AsyncAlign, string>;\n title: string;\n message: Record<AsyncAlign, string>;\n retryMargin: Record<AsyncAlign, string>;\n retry: string;\n};\n\nconst BLOCK_SPECS: Record<Exclude<AsyncVariant, 'inline'>, BlockSpec> = {\n elevated: {\n surface: ELEVATED_SURFACE_CLASSES,\n gap: 'gap-1',\n padding: { start: 'p-4', center: 'px-4 py-10', auto: 'p-4 lg:py-10' },\n title: 'text-body font-medium',\n message: { start: 'text-label', center: 'text-label', auto: 'text-label' },\n retryMargin: { start: 'mt-2', center: 'mt-2', auto: 'mt-2' },\n retry: RETRY_OUTLINE_CLASSES,\n },\n plain: {\n surface: '',\n gap: 'gap-1',\n padding: { start: 'px-4 py-5', center: 'px-4 py-12', auto: 'px-4 py-5 lg:py-12' },\n title: 'text-body leading-[normal] font-medium',\n message: {\n start: 'text-label leading-[normal]',\n center: 'text-label leading-[normal]',\n auto: 'text-label leading-[normal]',\n },\n retryMargin: { start: 'mt-2', center: 'mt-2', auto: 'mt-2' },\n retry: RETRY_OUTLINE_CLASSES,\n },\n emphasis: {\n surface: '',\n gap: 'gap-3',\n padding: { start: 'px-4 py-6', center: 'px-4 py-14', auto: 'px-4 py-6 lg:py-14' },\n title: 'text-title font-semibold',\n message: {\n start: 'text-label',\n center: 'text-body leading-[normal]',\n auto: 'text-label lg:text-body lg:leading-[normal]',\n },\n retryMargin: { start: 'mt-1', center: 'mt-2', auto: 'mt-1 lg:mt-2' },\n retry: RETRY_PRIMARY_CLASSES,\n },\n};\n\nconst ALIGN_CLASSES: Record<AsyncAlign, string> = {\n start: 'items-start',\n center: 'items-center text-center',\n auto: 'items-start lg:items-center lg:text-center',\n};\n\nconst INLINE_BOX_CLASSES = 'flex-row items-center justify-between gap-3 pt-1.5 pr-1.5 pb-2 pl-2.5';\n\n/**\n * The three states of a block that depends on a service call, next to the ready content.\n *\n * @example\n * <ui-async [state]=\"totalState()\" errorTitle=\"Total could not be loaded\" errorMessage=\"The server did not answer.\" retryLabel=\"Retry\" (retry)=\"reload()\">\n * <span asyncLoading><ui-skeleton shape=\"figure\" /></span>\n * <span asyncEmpty>Add a holding to see your total.</span>\n * <span>{{ total() }}</span>\n * </ui-async>\n */\n@Component({\n selector: 'ui-async',\n template: `\n @switch (shown()) {\n @case (null) {}\n @case ('loading') {\n <ng-content select=\"[asyncLoading]\" />\n }\n @case ('error') {\n <div aria-live=\"polite\" role=\"alert\" [class]=\"boxClasses()\">\n @if (variant() === 'inline') {\n <span class=\"text-label text-(--muted-foreground)\">{{ errorMessage() }}</span>\n } @else {\n @if (variant() === 'emphasis') {\n <h2 [class]=\"titleClasses()\">{{ errorTitle() }}</h2>\n } @else {\n <span [class]=\"titleClasses()\">{{ errorTitle() }}</span>\n }\n <span class=\"text-(--muted-foreground)\" [class]=\"messageClasses()\">{{ errorMessage() }}</span>\n }\n <button type=\"button\" [class]=\"retryButtonClasses()\" (click)=\"retry.emit()\">\n @if (retryIcon() || variant() !== 'inline') {\n <svg\n aria-hidden=\"true\"\n class=\"block flex-none fill-none stroke-current\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n [attr.height]=\"iconSize()\"\n [attr.width]=\"iconSize()\"\n >\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n }\n {{ retryLabel() }}\n </button>\n </div>\n }\n @case ('empty') {\n <ng-content select=\"[asyncEmpty]\" />\n }\n @default {\n <ng-content />\n }\n }\n `,\n host: {\n '[attr.aria-busy]': \"state() === 'loading' || null\",\n '[class.flex]': 'filling()',\n '[class.flex-col]': 'filling()',\n },\n})\nexport class UiAsync {\n readonly state = input.required<AsyncState>();\n readonly errorTitle = input<string>();\n readonly errorMessage = input<string>();\n readonly retryLabel = input<string>();\n /** Draws the rotate icon in the retry button. Only the `inline` variant honours `false`. */\n readonly retryIcon = input(true, { transform: booleanAttribute });\n readonly variant = input<AsyncVariant>('elevated');\n readonly align = input<AsyncAlign>('start');\n readonly card = input(false, { transform: booleanAttribute });\n readonly fill = input(false, { transform: booleanAttribute });\n readonly retry = output<void>();\n\n protected readonly shown = delayedState(this.state);\n\n protected readonly filling = computed(() => this.fill() && this.shown() === 'error');\n\n protected readonly iconSize = computed(() => (this.variant() === 'inline' ? 16 : 18));\n\n readonly #spec = computed(() => {\n const variant = this.variant();\n\n return variant === 'inline' ? null : BLOCK_SPECS[variant];\n });\n\n protected readonly boxClasses = computed(() => {\n const spec = this.#spec();\n const fill = this.fill() ? ' flex-1 justify-center' : '';\n\n if (spec === null) {\n return `flex ${INLINE_BOX_CLASSES}${this.card() ? ` ${CARD_SURFACE_CLASSES}` : ''}${this.fill() ? ' flex-1' : ''}`;\n }\n\n const surface = this.card() ? CARD_SURFACE_CLASSES : spec.surface;\n\n return `flex flex-col ${surface} ${spec.gap} ${ALIGN_CLASSES[this.align()]} ${spec.padding[this.align()]}${fill}`;\n });\n\n protected readonly titleClasses = computed(() => this.#spec()!.title);\n\n protected readonly messageClasses = computed(() => this.#spec()!.message[this.align()]);\n\n protected readonly retryButtonClasses = computed(() => {\n const spec = this.#spec();\n\n if (spec === null) {\n const spacing = this.retryIcon() ? RETRY_INLINE_ICON_CLASSES : RETRY_INLINE_TEXT_CLASSES;\n\n return `${RETRY_BASE_CLASSES} ${RETRY_OUTLINE_CLASSES} ${RETRY_INLINE_CLASSES} ${spacing}`;\n }\n\n return `${RETRY_BASE_CLASSES} ${spec.retry} ${RETRY_BLOCK_CLASSES} ${spec.retryMargin[this.align()]}`;\n });\n\n constructor() {\n holdTransitionsUntilRendered();\n }\n}\n"],"mappings":"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"}
@@ -1,71 +1,148 @@
1
- import * as i0 from '@angular/core';
2
- import { input, computed, Component, Directive } from '@angular/core';
3
-
4
- /** Available avatar sizes. `AvatarSize` is derived from this tuple. */
5
- const AVATAR_SIZES = ['sm', 'md', 'lg', 'auto'];
6
- const BASE_CLASSES = 'inline-flex items-center justify-center rounded-pill bg-(--muted) font-medium tabular-nums';
1
+ import * as i0 from "@angular/core";
2
+ import { Component, Directive, computed, input } from "@angular/core";
3
+ const AVATAR_SIZES = [
4
+ "sm",
5
+ "md",
6
+ "lg",
7
+ "auto"
8
+ ];
9
+ const BASE_CLASSES = "inline-flex items-center justify-center rounded-pill bg-(--muted) font-medium tabular-nums";
7
10
  const SIZE_CLASSES = {
8
- sm: 'size-8 text-caption',
9
- md: 'size-[34px] text-label',
10
- lg: 'size-14 text-title',
11
- auto: 'size-[34px] text-label lg:size-8 lg:text-caption',
11
+ sm: "size-8 text-caption",
12
+ md: "size-[34px] text-label",
13
+ lg: "size-14 text-title",
14
+ auto: "size-[34px] text-label lg:size-8 lg:text-caption"
12
15
  };
13
- /**
14
- * Initials in a disc, standing in for a person. Single-user application: there is exactly one.
15
- *
16
- * @example
17
- * <ui-avatar initials="JR" label="My account" />
18
- */
19
- class UiAvatar {
20
- initials = input.required(/* @ts-ignore */
21
- ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
22
- label = input.required(/* @ts-ignore */
23
- ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
24
- size = input('md', /* @ts-ignore */
25
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
26
- classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`, /* @ts-ignore */
27
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
28
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
29
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.7", type: UiAvatar, isStandalone: true, selector: "ui-avatar", inputs: { initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "img" }, properties: { "attr.aria-label": "label()", "class": "classes()" } }, ngImport: i0, template: '<span aria-hidden="true">{{ initials() }}</span>', isInline: true });
30
- }
31
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAvatar, decorators: [{
32
- type: Component,
33
- args: [{
34
- selector: 'ui-avatar',
35
- template: '<span aria-hidden="true">{{ initials() }}</span>',
36
- host: {
37
- role: 'img',
38
- '[attr.aria-label]': 'label()',
39
- '[class]': 'classes()',
40
- },
41
- }]
42
- }], propDecorators: { initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
43
- /**
44
- * Round hit area around a `ui-avatar` that links somewhere: 44px on touch, 40px from 64rem, with a
45
- * glow on hover and the press scale. On the current page (`aria-current="page"`, which `routerLinkActive`
46
- * sets through `ariaCurrentWhenActive`) it holds a soft halo, drawn at once when the route changes. The avatar
47
- * itself keeps its own size.
48
- *
49
- * @example
50
- * <a uiAvatarLink routerLink="/profile"><ui-avatar initials="JR" label="Profile" size="auto" /></a>
51
- */
52
- class UiAvatarLink {
53
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAvatarLink, deps: [], target: i0.ɵɵFactoryTarget.Directive });
54
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.7", type: UiAvatarLink, isStandalone: true, selector: "a[uiAvatarLink], button[uiAvatarLink]", host: { classAttribute: "rounded-pill grid size-11 lg:size-10 place-items-center cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) aria-[current=page]:bg-transparent aria-[current=page]:bg-[image:linear-gradient(var(--soft),var(--soft))] active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)" }, ngImport: i0 });
55
- }
56
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiAvatarLink, decorators: [{
57
- type: Directive,
58
- args: [{
59
- selector: 'a[uiAvatarLink], button[uiAvatarLink]',
60
- host: {
61
- class: 'rounded-pill grid size-11 lg:size-10 place-items-center cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) aria-[current=page]:bg-transparent aria-[current=page]:bg-[image:linear-gradient(var(--soft),var(--soft))] active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)',
62
- },
63
- }]
64
- }] });
65
-
66
- /**
67
- * Generated bundle index. Do not edit.
68
- */
69
-
16
+ var UiAvatar = class UiAvatar {
17
+ initials = input.required(...ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []);
18
+ label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
19
+ size = input("md", ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
20
+ classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
21
+ static ɵfac = i0.ɵɵngDeclareFactory({
22
+ minVersion: "12.0.0",
23
+ version: "22.2.0",
24
+ ngImport: i0,
25
+ type: UiAvatar,
26
+ deps: [],
27
+ target: i0.ɵɵFactoryTarget.Component
28
+ });
29
+ static ɵcmp = i0.ɵɵngDeclareComponent({
30
+ minVersion: "17.1.0",
31
+ version: "22.2.0",
32
+ type: UiAvatar,
33
+ isStandalone: true,
34
+ selector: "ui-avatar",
35
+ inputs: {
36
+ initials: {
37
+ classPropertyName: "initials",
38
+ publicName: "initials",
39
+ isSignal: true,
40
+ isRequired: true,
41
+ transformFunction: null
42
+ },
43
+ label: {
44
+ classPropertyName: "label",
45
+ publicName: "label",
46
+ isSignal: true,
47
+ isRequired: true,
48
+ transformFunction: null
49
+ },
50
+ size: {
51
+ classPropertyName: "size",
52
+ publicName: "size",
53
+ isSignal: true,
54
+ isRequired: false,
55
+ transformFunction: null
56
+ }
57
+ },
58
+ host: {
59
+ attributes: { "role": "img" },
60
+ properties: {
61
+ "attr.aria-label": "label()",
62
+ "class": "classes()"
63
+ }
64
+ },
65
+ ngImport: i0,
66
+ template: "<span aria-hidden=\"true\">{{ initials() }}</span>",
67
+ isInline: true
68
+ });
69
+ };
70
+ i0.ɵɵngDeclareClassMetadata({
71
+ minVersion: "12.0.0",
72
+ version: "22.2.0",
73
+ ngImport: i0,
74
+ type: UiAvatar,
75
+ decorators: [{
76
+ type: Component,
77
+ args: [{
78
+ selector: "ui-avatar",
79
+ template: "<span aria-hidden=\"true\">{{ initials() }}</span>",
80
+ host: {
81
+ role: "img",
82
+ "[attr.aria-label]": "label()",
83
+ "[class]": "classes()"
84
+ }
85
+ }]
86
+ }],
87
+ propDecorators: {
88
+ initials: [{
89
+ type: i0.Input,
90
+ args: [{
91
+ isSignal: true,
92
+ alias: "initials",
93
+ required: true
94
+ }]
95
+ }],
96
+ label: [{
97
+ type: i0.Input,
98
+ args: [{
99
+ isSignal: true,
100
+ alias: "label",
101
+ required: true
102
+ }]
103
+ }],
104
+ size: [{
105
+ type: i0.Input,
106
+ args: [{
107
+ isSignal: true,
108
+ alias: "size",
109
+ required: false
110
+ }]
111
+ }]
112
+ }
113
+ });
114
+ var UiAvatarLink = class UiAvatarLink {
115
+ static ɵfac = i0.ɵɵngDeclareFactory({
116
+ minVersion: "12.0.0",
117
+ version: "22.2.0",
118
+ ngImport: i0,
119
+ type: UiAvatarLink,
120
+ deps: [],
121
+ target: i0.ɵɵFactoryTarget.Directive
122
+ });
123
+ static ɵdir = i0.ɵɵngDeclareDirective({
124
+ minVersion: "14.0.0",
125
+ version: "22.2.0",
126
+ type: UiAvatarLink,
127
+ isStandalone: true,
128
+ selector: "a[uiAvatarLink], button[uiAvatarLink]",
129
+ host: { classAttribute: "rounded-pill grid size-11 lg:size-10 place-items-center cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) aria-[current=page]:bg-transparent aria-[current=page]:bg-[image:linear-gradient(var(--soft),var(--soft))] active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)" },
130
+ ngImport: i0
131
+ });
132
+ };
133
+ i0.ɵɵngDeclareClassMetadata({
134
+ minVersion: "12.0.0",
135
+ version: "22.2.0",
136
+ ngImport: i0,
137
+ type: UiAvatarLink,
138
+ decorators: [{
139
+ type: Directive,
140
+ args: [{
141
+ selector: "a[uiAvatarLink], button[uiAvatarLink]",
142
+ host: { class: "rounded-pill grid size-11 lg:size-10 place-items-center cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) aria-[current=page]:bg-transparent aria-[current=page]:bg-[image:linear-gradient(var(--soft),var(--soft))] active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)" }
143
+ }]
144
+ }]
145
+ });
70
146
  export { AVATAR_SIZES, UiAvatar, UiAvatarLink };
71
- //# sourceMappingURL=joanroucoux-cairn-ui-avatar.mjs.map
147
+
148
+ //# sourceMappingURL=joanroucoux-cairn-ui-avatar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-avatar.mjs","sources":["../../../projects/ui/avatar/avatar.ts","../../../projects/ui/avatar/joanroucoux-cairn-ui-avatar.ts"],"sourcesContent":["import { Component, Directive, computed, input } from '@angular/core';\n\n/** Available avatar sizes. `AvatarSize` is derived from this tuple. */\nexport const AVATAR_SIZES = ['sm', 'md', 'lg', 'auto'] as const;\nexport type AvatarSize = (typeof AVATAR_SIZES)[number];\n\nconst BASE_CLASSES = 'inline-flex items-center justify-center rounded-pill bg-(--muted) font-medium tabular-nums';\n\nconst SIZE_CLASSES: Record<AvatarSize, string> = {\n sm: 'size-8 text-caption',\n md: 'size-[34px] text-label',\n lg: 'size-14 text-title',\n auto: 'size-[34px] text-label lg:size-8 lg:text-caption',\n};\n\n/**\n * Initials in a disc, standing in for a person. Single-user application: there is exactly one.\n *\n * @example\n * <ui-avatar initials=\"JR\" label=\"My account\" />\n */\n@Component({\n selector: 'ui-avatar',\n template: '<span aria-hidden=\"true\">{{ initials() }}</span>',\n host: {\n role: 'img',\n '[attr.aria-label]': 'label()',\n '[class]': 'classes()',\n },\n})\nexport class UiAvatar {\n readonly initials = input.required<string>();\n readonly label = input.required<string>();\n readonly size = input<AvatarSize>('md');\n\n protected readonly classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`);\n}\n\n/**\n * Round hit area around a `ui-avatar` that links somewhere: 44px on touch, 40px from 64rem, with a\n * glow on hover and the press scale. On the current page (`aria-current=\"page\"`, which `routerLinkActive`\n * sets through `ariaCurrentWhenActive`) it holds a soft halo, drawn at once when the route changes. The avatar\n * itself keeps its own size.\n *\n * @example\n * <a uiAvatarLink routerLink=\"/profile\"><ui-avatar initials=\"JR\" label=\"Profile\" size=\"auto\" /></a>\n */\n@Directive({\n selector: 'a[uiAvatarLink], button[uiAvatarLink]',\n host: {\n class:\n 'rounded-pill grid size-11 lg:size-10 place-items-center cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) aria-[current=page]:bg-transparent aria-[current=page]:bg-[image:linear-gradient(var(--soft),var(--soft))] active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)',\n },\n})\nexport class UiAvatarLink {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;AAEA;AACO,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM;AAGrD,MAAM,YAAY,GAAG,4FAA4F;AAEjH,MAAM,YAAY,GAA+B;AAC/C,IAAA,EAAE,EAAE,qBAAqB;AACzB,IAAA,EAAE,EAAE,wBAAwB;AAC5B,IAAA,EAAE,EAAE,oBAAoB;AACxB,IAAA,IAAI,EAAE,kDAAkD;CACzD;AAED;;;;;AAKG;MAUU,QAAQ,CAAA;IACV,QAAQ,GAAG,KAAK,CAAC,QAAQ;iFAAU;IACnC,KAAK,GAAG,KAAK,CAAC,QAAQ;8EAAU;IAChC,IAAI,GAAG,KAAK,CAAa,IAAI;6EAAC;AAEpB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA,CAAE;gFAAC;uGALhF,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,QAAQ,0iBAPT,kDAAkD,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA;;2FAOjD,QAAQ,EAAA,UAAA,EAAA,CAAA;kBATpB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,QAAQ,EAAE,kDAAkD;AAC5D,oBAAA,IAAI,EAAE;AACJ,wBAAA,IAAI,EAAE,KAAK;AACX,wBAAA,mBAAmB,EAAE,SAAS;AAC9B,wBAAA,SAAS,EAAE,WAAW;AACvB,qBAAA;AACF,iBAAA;;AASD;;;;;;;;AAQG;MAQU,YAAY,CAAA;uGAAZ,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAZ,YAAY,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,uCAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,qcAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAZ,YAAY,EAAA,UAAA,EAAA,CAAA;kBAPxB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,uCAAuC;AACjD,oBAAA,IAAI,EAAE;AACJ,wBAAA,KAAK,EACH,qcAAqc;AACxc,qBAAA;AACF,iBAAA;;;ACrDD;;AAEG;;;;"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-avatar.mjs","names":[],"sources":["../../../projects/ui/avatar/avatar.ts"],"sourcesContent":["import { Component, Directive, computed, input } from '@angular/core';\n\n/** Available avatar sizes. */\nexport const AVATAR_SIZES = ['sm', 'md', 'lg', 'auto'] as const;\nexport type AvatarSize = (typeof AVATAR_SIZES)[number];\n\nconst BASE_CLASSES = 'inline-flex items-center justify-center rounded-pill bg-(--muted) font-medium tabular-nums';\n\nconst SIZE_CLASSES: Record<AvatarSize, string> = {\n sm: 'size-8 text-caption',\n md: 'size-[34px] text-label',\n lg: 'size-14 text-title',\n auto: 'size-[34px] text-label lg:size-8 lg:text-caption',\n};\n\n/**\n * Initials in a disc, standing in for a person.\n *\n * @example\n * <ui-avatar initials=\"JR\" label=\"My account\" />\n */\n@Component({\n selector: 'ui-avatar',\n template: '<span aria-hidden=\"true\">{{ initials() }}</span>',\n host: {\n role: 'img',\n '[attr.aria-label]': 'label()',\n '[class]': 'classes()',\n },\n})\nexport class UiAvatar {\n readonly initials = input.required<string>();\n readonly label = input.required<string>();\n readonly size = input<AvatarSize>('md');\n\n protected readonly classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`);\n}\n\n/**\n * Round hit area around a `ui-avatar` that links somewhere. On the current page\n * (`aria-current=\"page\"`, set by `routerLinkActive` through `ariaCurrentWhenActive`) it holds a\n * soft halo.\n *\n * @example\n * <a uiAvatarLink routerLink=\"/profile\"><ui-avatar initials=\"JR\" label=\"Profile\" size=\"auto\" /></a>\n */\n@Directive({\n selector: 'a[uiAvatarLink], button[uiAvatarLink]',\n host: {\n class:\n 'rounded-pill grid size-11 lg:size-10 place-items-center cursor-pointer select-none touch-manipulation transition-[scale,background-color] [transition-duration:var(--duration-press),var(--duration-fast)] ease-out hover:bg-(--glow) aria-[current=page]:bg-transparent aria-[current=page]:bg-[image:linear-gradient(var(--soft),var(--soft))] active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)',\n },\n})\nexport class UiAvatarLink {}\n"],"mappings":";;AAGA,MAAa,eAAe;CAAC;CAAM;CAAM;CAAM;AAAM;AAGrD,MAAM,eAAe;AAErB,MAAM,eAA2C;CAC/C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;AACP;AAiBD,IAAa,WAAb,MAAa,SAAQ;CACV,WAAW,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACnC,QAAQ,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAChC,OAAO,MAAkB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEpB,UAAU,eAAe,GAAG,aAAY,GAAI,aAAa,KAAK,KAAI,MAAM,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CALhF,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,UAAA;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;EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,QAAA,MAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,SAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UAPT;EAAkD,UAAA;CAAA,CAAA;;AAOjD,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAQ,YAAA,CAAA;EATpB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,UAAU;GACV,MAAM;IACJ,MAAM;IACN,qBAAqB;IACrB,WAAW;GACZ;EACF,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBD,IAAa,eAAb,MAAa,aAAY;CAAZ,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAY,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAZ,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAY,cAAA;EAAA,UAAA;EAAA,MAAA,EAAA,gBAAA,scAAA;EAAA,UAAA;CAAA,CAAA;;AAAZ,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAY,YAAA,CAAA;EAPxB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM,EACJ,OACE,scACH;EACF,CAAA"}
@@ -1,34 +1,60 @@
1
- import * as i0 from '@angular/core';
2
- import { input, computed, Component } from '@angular/core';
3
- import { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';
4
-
5
- /** Available back link sizes. `BackLinkSize` is derived from this tuple. */
6
- const BACK_LINK_SIZES = ['md', 'sm', 'header'];
7
- const BASE_CLASSES = 'inline-flex items-center gap-0.5 rounded-control text-body font-medium whitespace-nowrap cursor-pointer select-none touch-manipulation transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-(--ring)';
1
+ import * as i0 from "@angular/core";
2
+ import { Component, ElementRef, HostAttributeToken, computed, inject, input } from "@angular/core";
3
+ import { holdTransitionsUntilRendered } from "@joanroucoux/cairn-ui/motion";
4
+ const BACK_LINK_SIZES = [
5
+ "md",
6
+ "sm",
7
+ "header",
8
+ "inline"
9
+ ];
10
+ const BASE_CLASSES = "inline-flex items-center gap-0.5 rounded-control font-medium whitespace-nowrap cursor-pointer select-none touch-manipulation transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-(--ring)";
8
11
  const SIZE_CLASSES = {
9
- md: 'h-11 pr-3 pl-1 text-(--foreground) focus-visible:outline-offset-2',
10
- sm: 'h-9 pr-2 pl-0.5 text-(--muted-foreground) hover:bg-(--glow) hover:text-(--foreground) focus-visible:outline-offset-2',
11
- header: 'h-11 pr-3 pl-1 text-(--foreground) focus-visible:-outline-offset-2',
12
+ md: "h-11 pr-3 pl-1 text-body text-(--foreground) focus-visible:outline-offset-2",
13
+ sm: "h-9 pr-2 pl-0.5 text-body text-(--muted-foreground) hover:bg-(--glow) hover:text-(--foreground) focus-visible:outline-offset-2",
14
+ header: "h-11 pr-3 pl-1 text-body text-(--foreground) focus-visible:-outline-offset-2",
15
+ inline: "h-11 pointer-fine:h-9 pr-2 pl-0.5 text-label text-(--muted-foreground) hover:text-(--foreground) focus-visible:outline-offset-2"
16
+ };
17
+ const CHEVRON = {
18
+ md: 22,
19
+ sm: 22,
20
+ header: 24,
21
+ inline: 18
12
22
  };
13
- const CHEVRON = { md: 22, sm: 22, header: 24 };
14
- /**
15
- * Link back to the parent screen: a chevron and the name of the destination.
16
- *
17
- * @example
18
- * <a ui-back-link routerLink="/accounts">Accounts</a>
19
- */
20
- class UiBackLink {
21
- size = input('md', /* @ts-ignore */
22
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
23
- chevron = computed(() => CHEVRON[this.size()], /* @ts-ignore */
24
- ...(ngDevMode ? [{ debugName: "chevron" }] : /* istanbul ignore next */ []));
25
- classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`, /* @ts-ignore */
26
- ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
27
- constructor() {
28
- holdTransitionsUntilRendered();
29
- }
30
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiBackLink, deps: [], target: i0.ɵɵFactoryTarget.Component });
31
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.7", type: UiBackLink, isStandalone: true, selector: "a[ui-back-link]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: `
23
+ var UiBackLink = class UiBackLink {
24
+ size = input("md", ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
25
+ type = inject(new HostAttributeToken("type"), { optional: true }) ?? (inject(ElementRef).nativeElement.tagName === "BUTTON" ? "button" : null);
26
+ chevron = computed(() => CHEVRON[this.size()], ...ngDevMode ? [{ debugName: "chevron" }] : /* istanbul ignore next */ []);
27
+ classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
28
+ constructor() {
29
+ holdTransitionsUntilRendered();
30
+ }
31
+ static ɵfac = i0.ɵɵngDeclareFactory({
32
+ minVersion: "12.0.0",
33
+ version: "22.2.0",
34
+ ngImport: i0,
35
+ type: UiBackLink,
36
+ deps: [],
37
+ target: i0.ɵɵFactoryTarget.Component
38
+ });
39
+ static ɵcmp = i0.ɵɵngDeclareComponent({
40
+ minVersion: "17.1.0",
41
+ version: "22.2.0",
42
+ type: UiBackLink,
43
+ isStandalone: true,
44
+ selector: "a[ui-back-link], button[ui-back-link]",
45
+ inputs: { size: {
46
+ classPropertyName: "size",
47
+ publicName: "size",
48
+ isSignal: true,
49
+ isRequired: false,
50
+ transformFunction: null
51
+ } },
52
+ host: { properties: {
53
+ "class": "classes()",
54
+ "attr.type": "type"
55
+ } },
56
+ ngImport: i0,
57
+ template: `
32
58
  <svg
33
59
  aria-hidden="true"
34
60
  fill="none"
@@ -43,13 +69,20 @@ class UiBackLink {
43
69
  <path d="m15 18-6-6 6-6" />
44
70
  </svg>
45
71
  <ng-content />
46
- `, isInline: true });
47
- }
48
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiBackLink, decorators: [{
49
- type: Component,
50
- args: [{
51
- selector: 'a[ui-back-link]',
52
- template: `
72
+ `,
73
+ isInline: true
74
+ });
75
+ };
76
+ i0.ɵɵngDeclareClassMetadata({
77
+ minVersion: "12.0.0",
78
+ version: "22.2.0",
79
+ ngImport: i0,
80
+ type: UiBackLink,
81
+ decorators: [{
82
+ type: Component,
83
+ args: [{
84
+ selector: "a[ui-back-link], button[ui-back-link]",
85
+ template: `
53
86
  <svg
54
87
  aria-hidden="true"
55
88
  fill="none"
@@ -65,15 +98,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
65
98
  </svg>
66
99
  <ng-content />
67
100
  `,
68
- host: {
69
- '[class]': 'classes()',
70
- },
71
- }]
72
- }], ctorParameters: () => [], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
73
-
74
- /**
75
- * Generated bundle index. Do not edit.
76
- */
77
-
101
+ host: {
102
+ "[class]": "classes()",
103
+ "[attr.type]": "type"
104
+ }
105
+ }]
106
+ }],
107
+ ctorParameters: () => [],
108
+ propDecorators: { size: [{
109
+ type: i0.Input,
110
+ args: [{
111
+ isSignal: true,
112
+ alias: "size",
113
+ required: false
114
+ }]
115
+ }] }
116
+ });
78
117
  export { BACK_LINK_SIZES, UiBackLink };
79
- //# sourceMappingURL=joanroucoux-cairn-ui-back-link.mjs.map
118
+
119
+ //# sourceMappingURL=joanroucoux-cairn-ui-back-link.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-back-link.mjs","sources":["../../../projects/ui/back-link/back-link.ts","../../../projects/ui/back-link/joanroucoux-cairn-ui-back-link.ts"],"sourcesContent":["import { Component, computed, input } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\n/** Available back link sizes. `BackLinkSize` is derived from this tuple. */\nexport const BACK_LINK_SIZES = ['md', 'sm', 'header'] as const;\nexport type BackLinkSize = (typeof BACK_LINK_SIZES)[number];\n\nconst BASE_CLASSES =\n 'inline-flex items-center gap-0.5 rounded-control text-body font-medium whitespace-nowrap cursor-pointer select-none touch-manipulation transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-(--ring)';\n\nconst SIZE_CLASSES: Record<BackLinkSize, string> = {\n md: 'h-11 pr-3 pl-1 text-(--foreground) focus-visible:outline-offset-2',\n sm: 'h-9 pr-2 pl-0.5 text-(--muted-foreground) hover:bg-(--glow) hover:text-(--foreground) focus-visible:outline-offset-2',\n header: 'h-11 pr-3 pl-1 text-(--foreground) focus-visible:-outline-offset-2',\n};\n\nconst CHEVRON: Record<BackLinkSize, number> = { md: 22, sm: 22, header: 24 };\n\n/**\n * Link back to the parent screen: a chevron and the name of the destination.\n *\n * @example\n * <a ui-back-link routerLink=\"/accounts\">Accounts</a>\n */\n@Component({\n selector: 'a[ui-back-link]',\n template: `\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n [attr.height]=\"chevron()\"\n [attr.width]=\"chevron()\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n <ng-content />\n `,\n host: {\n '[class]': 'classes()',\n },\n})\nexport class UiBackLink {\n readonly size = input<BackLinkSize>('md');\n\n protected readonly chevron = computed(() => CHEVRON[this.size()]);\n protected readonly classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`);\n\n constructor() {\n holdTransitionsUntilRendered();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAIA;AACO,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ;AAGpD,MAAM,YAAY,GAChB,qWAAqW;AAEvW,MAAM,YAAY,GAAiC;AACjD,IAAA,EAAE,EAAE,mEAAmE;AACvE,IAAA,EAAE,EAAE,sHAAsH;AAC1H,IAAA,MAAM,EAAE,oEAAoE;CAC7E;AAED,MAAM,OAAO,GAAiC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;AAE5E;;;;;AAKG;MAuBU,UAAU,CAAA;IACZ,IAAI,GAAG,KAAK,CAAe,IAAI;6EAAC;AAEtB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gFAAC;AAC9C,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA,CAAE;gFAAC;AAE3F,IAAA,WAAA,GAAA;AACE,QAAA,4BAA4B,EAAE;IAChC;uGARW,UAAU,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAV,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAU,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,WAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EApBX;;;;;;;;;;;;;;;AAeT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA;;2FAKU,UAAU,EAAA,UAAA,EAAA,CAAA;kBAtBtB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,iBAAiB;AAC3B,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;AAeT,EAAA,CAAA;AACD,oBAAA,IAAI,EAAE;AACJ,wBAAA,SAAS,EAAE,WAAW;AACvB,qBAAA;AACF,iBAAA;;;AC9CD;;AAEG;;;;"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-back-link.mjs","names":[],"sources":["../../../projects/ui/back-link/back-link.ts"],"sourcesContent":["import { Component, ElementRef, HostAttributeToken, computed, inject, input } from '@angular/core';\n\nimport { holdTransitionsUntilRendered } from '@joanroucoux/cairn-ui/motion';\n\n/** Available back link sizes. */\nexport const BACK_LINK_SIZES = ['md', 'sm', 'header', 'inline'] as const;\nexport type BackLinkSize = (typeof BACK_LINK_SIZES)[number];\n\nconst BASE_CLASSES =\n 'inline-flex items-center gap-0.5 rounded-control font-medium whitespace-nowrap cursor-pointer select-none touch-manipulation transition-[scale,background-color,color] [transition-duration:var(--duration-press),var(--duration-fast),var(--duration-fast)] ease-out active:scale-(--press-scale) focus-visible:outline-2 focus-visible:outline-(--ring)';\n\nconst SIZE_CLASSES: Record<BackLinkSize, string> = {\n md: 'h-11 pr-3 pl-1 text-body text-(--foreground) focus-visible:outline-offset-2',\n sm: 'h-9 pr-2 pl-0.5 text-body text-(--muted-foreground) hover:bg-(--glow) hover:text-(--foreground) focus-visible:outline-offset-2',\n header: 'h-11 pr-3 pl-1 text-body text-(--foreground) focus-visible:-outline-offset-2',\n inline:\n 'h-11 pointer-fine:h-9 pr-2 pl-0.5 text-label text-(--muted-foreground) hover:text-(--foreground) focus-visible:outline-offset-2',\n};\n\nconst CHEVRON: Record<BackLinkSize, number> = { md: 22, sm: 22, header: 24, inline: 18 };\n\n/**\n * Link back to the parent screen: a chevron and the name of the destination. On a `button`, it\n * goes back inside the current view, such as from a form to the search that led to it.\n *\n * @example\n * <a ui-back-link routerLink=\"/accounts\">Accounts</a>\n */\n@Component({\n selector: 'a[ui-back-link], button[ui-back-link]',\n template: `\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"1.75\"\n viewBox=\"0 0 24 24\"\n [attr.height]=\"chevron()\"\n [attr.width]=\"chevron()\"\n >\n <path d=\"m15 18-6-6 6-6\" />\n </svg>\n <ng-content />\n `,\n host: {\n '[class]': 'classes()',\n '[attr.type]': 'type',\n },\n})\nexport class UiBackLink {\n readonly size = input<BackLinkSize>('md');\n\n protected readonly type =\n inject(new HostAttributeToken('type'), { optional: true }) ??\n (inject<ElementRef<HTMLElement>>(ElementRef).nativeElement.tagName === 'BUTTON' ? 'button' : null);\n protected readonly chevron = computed(() => CHEVRON[this.size()]);\n protected readonly classes = computed(() => `${BASE_CLASSES} ${SIZE_CLASSES[this.size()]}`);\n\n constructor() {\n holdTransitionsUntilRendered();\n }\n}\n"],"mappings":";;;AAKA,MAAa,kBAAkB;CAAC;CAAM;CAAM;CAAU;AAAQ;AAG9D,MAAM,eACJ;AAEF,MAAM,eAA6C;CACjD,IAAI;CACJ,IAAI;CACJ,QAAQ;CACR,QACE;AACH;AAED,MAAM,UAAwC;CAAE,IAAI;CAAI,IAAI;CAAI,QAAQ;CAAI,QAAQ;AAAE;AAgCtF,IAAa,aAAb,MAAa,WAAU;CACZ,OAAO,MAAoB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAEtB,OACjB,OAAO,IAAI,mBAAmB,MAAM,GAAG,EAAE,UAAU,KAAI,CAAE,MACxD,OAAgC,UAAU,CAAC,CAAC,cAAc,YAAY,WAAW,WAAW;CAC5E,UAAU,eAAe,QAAQ,KAAK,KAAI,IAAI,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAC9C,UAAU,eAAe,GAAG,aAAY,GAAI,aAAa,KAAK,KAAI,MAAM,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAE3F,cAAA;EACE,6BAA4B;CAC9B;CAXW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAU,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAV,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAU,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,MAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,MAAA,EAAA,YAAA;GAAA,SAAA;GAAA,aAAA;EAAA,EAAA;EAAA,UAAA;EAAA,UArBX;;;;;;;;;;;;;;;;EAeT,UAAA;CAAA,CAAA;;AAMU,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAU,YAAA,CAAA;EAvBtB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,UAAU;;;;;;;;;;;;;;;;GAgBV,MAAM;IACJ,WAAW;IACX,eAAe;GAChB;EACF,CAAA"}