@hyalo/angular 0.1.0 → 0.3.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 (198) hide show
  1. package/CHANGELOG.md +95 -41
  2. package/README.md +46 -32
  3. package/fesm2022/hyalo-angular-accordion.mjs +6 -6
  4. package/fesm2022/hyalo-angular-accordion.mjs.map +1 -1
  5. package/fesm2022/hyalo-angular-alert.mjs +171 -0
  6. package/fesm2022/hyalo-angular-alert.mjs.map +1 -0
  7. package/fesm2022/hyalo-angular-aspect-ratio.mjs +64 -0
  8. package/fesm2022/hyalo-angular-aspect-ratio.mjs.map +1 -0
  9. package/fesm2022/hyalo-angular-avatar.mjs +169 -0
  10. package/fesm2022/hyalo-angular-avatar.mjs.map +1 -0
  11. package/fesm2022/hyalo-angular-badge.mjs +268 -0
  12. package/fesm2022/hyalo-angular-badge.mjs.map +1 -0
  13. package/fesm2022/hyalo-angular-bento.mjs +132 -0
  14. package/fesm2022/hyalo-angular-bento.mjs.map +1 -0
  15. package/fesm2022/hyalo-angular-blocks.mjs +985 -0
  16. package/fesm2022/hyalo-angular-blocks.mjs.map +1 -0
  17. package/fesm2022/hyalo-angular-border-beam.mjs +73 -0
  18. package/fesm2022/hyalo-angular-border-beam.mjs.map +1 -0
  19. package/fesm2022/hyalo-angular-breadcrumb.mjs +77 -0
  20. package/fesm2022/hyalo-angular-breadcrumb.mjs.map +1 -0
  21. package/fesm2022/hyalo-angular-button-group.mjs +90 -0
  22. package/fesm2022/hyalo-angular-button-group.mjs.map +1 -0
  23. package/fesm2022/hyalo-angular-button.mjs +4 -3
  24. package/fesm2022/hyalo-angular-button.mjs.map +1 -1
  25. package/fesm2022/hyalo-angular-card.mjs +2 -2
  26. package/fesm2022/hyalo-angular-card.mjs.map +1 -1
  27. package/fesm2022/hyalo-angular-carousel.mjs +709 -0
  28. package/fesm2022/hyalo-angular-carousel.mjs.map +1 -0
  29. package/fesm2022/hyalo-angular-chapter-nav.mjs +336 -0
  30. package/fesm2022/hyalo-angular-chapter-nav.mjs.map +1 -0
  31. package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs +5 -0
  32. package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs.map +1 -0
  33. package/fesm2022/hyalo-angular-chart.mjs +391 -0
  34. package/fesm2022/hyalo-angular-chart.mjs.map +1 -0
  35. package/fesm2022/hyalo-angular-choice.mjs +2 -1
  36. package/fesm2022/hyalo-angular-choice.mjs.map +1 -1
  37. package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs +40 -0
  38. package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs.map +1 -0
  39. package/fesm2022/hyalo-angular-code-block.mjs +161 -0
  40. package/fesm2022/hyalo-angular-code-block.mjs.map +1 -0
  41. package/fesm2022/hyalo-angular-command.mjs +193 -0
  42. package/fesm2022/hyalo-angular-command.mjs.map +1 -0
  43. package/fesm2022/hyalo-angular-copy.mjs +138 -0
  44. package/fesm2022/hyalo-angular-copy.mjs.map +1 -0
  45. package/fesm2022/hyalo-angular-core.mjs +424 -0
  46. package/fesm2022/hyalo-angular-core.mjs.map +1 -0
  47. package/fesm2022/hyalo-angular-description-list.mjs +57 -0
  48. package/fesm2022/hyalo-angular-description-list.mjs.map +1 -0
  49. package/fesm2022/hyalo-angular-dialog.mjs +51 -22
  50. package/fesm2022/hyalo-angular-dialog.mjs.map +1 -1
  51. package/fesm2022/hyalo-angular-divider.mjs +66 -0
  52. package/fesm2022/hyalo-angular-divider.mjs.map +1 -0
  53. package/fesm2022/hyalo-angular-empty-state.mjs +123 -0
  54. package/fesm2022/hyalo-angular-empty-state.mjs.map +1 -0
  55. package/fesm2022/hyalo-angular-field.mjs +41 -9
  56. package/fesm2022/hyalo-angular-field.mjs.map +1 -1
  57. package/fesm2022/hyalo-angular-filter.mjs +309 -0
  58. package/fesm2022/hyalo-angular-filter.mjs.map +1 -0
  59. package/fesm2022/hyalo-angular-hotspot.mjs +225 -0
  60. package/fesm2022/hyalo-angular-hotspot.mjs.map +1 -0
  61. package/fesm2022/hyalo-angular-hover-card.mjs +233 -0
  62. package/fesm2022/hyalo-angular-hover-card.mjs.map +1 -0
  63. package/fesm2022/hyalo-angular-icon.mjs +42 -0
  64. package/fesm2022/hyalo-angular-icon.mjs.map +1 -1
  65. package/fesm2022/hyalo-angular-image-compare.mjs +168 -0
  66. package/fesm2022/hyalo-angular-image-compare.mjs.map +1 -0
  67. package/fesm2022/hyalo-angular-interaction.mjs +32 -41
  68. package/fesm2022/hyalo-angular-interaction.mjs.map +1 -1
  69. package/fesm2022/hyalo-angular-kbd.mjs +41 -0
  70. package/fesm2022/hyalo-angular-kbd.mjs.map +1 -0
  71. package/fesm2022/hyalo-angular-lightbox.mjs +228 -0
  72. package/fesm2022/hyalo-angular-lightbox.mjs.map +1 -0
  73. package/fesm2022/hyalo-angular-link.mjs +42 -0
  74. package/fesm2022/hyalo-angular-link.mjs.map +1 -0
  75. package/fesm2022/hyalo-angular-list.mjs +131 -0
  76. package/fesm2022/hyalo-angular-list.mjs.map +1 -0
  77. package/fesm2022/hyalo-angular-marquee.mjs +197 -0
  78. package/fesm2022/hyalo-angular-marquee.mjs.map +1 -0
  79. package/fesm2022/hyalo-angular-menu.mjs +423 -0
  80. package/fesm2022/hyalo-angular-menu.mjs.map +1 -0
  81. package/fesm2022/hyalo-angular-mesh.mjs +126 -0
  82. package/fesm2022/hyalo-angular-mesh.mjs.map +1 -0
  83. package/fesm2022/hyalo-angular-motion.mjs +620 -0
  84. package/fesm2022/hyalo-angular-motion.mjs.map +1 -0
  85. package/fesm2022/hyalo-angular-navbar.mjs +1 -1
  86. package/fesm2022/hyalo-angular-navbar.mjs.map +1 -1
  87. package/fesm2022/hyalo-angular-navigation-menu.mjs +222 -0
  88. package/fesm2022/hyalo-angular-navigation-menu.mjs.map +1 -0
  89. package/fesm2022/hyalo-angular-number-ticker.mjs +174 -0
  90. package/fesm2022/hyalo-angular-number-ticker.mjs.map +1 -0
  91. package/fesm2022/hyalo-angular-overlay.mjs +71 -2
  92. package/fesm2022/hyalo-angular-overlay.mjs.map +1 -1
  93. package/fesm2022/hyalo-angular-pagination.mjs +187 -0
  94. package/fesm2022/hyalo-angular-pagination.mjs.map +1 -0
  95. package/fesm2022/hyalo-angular-popover.mjs +34 -5
  96. package/fesm2022/hyalo-angular-popover.mjs.map +1 -1
  97. package/fesm2022/hyalo-angular-progress.mjs +209 -0
  98. package/fesm2022/hyalo-angular-progress.mjs.map +1 -0
  99. package/fesm2022/hyalo-angular-progressive-blur.mjs +73 -0
  100. package/fesm2022/hyalo-angular-progressive-blur.mjs.map +1 -0
  101. package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs +186 -0
  102. package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs.map +1 -0
  103. package/fesm2022/hyalo-angular-refraction.mjs +178 -0
  104. package/fesm2022/hyalo-angular-refraction.mjs.map +1 -0
  105. package/fesm2022/hyalo-angular-scroll-area.mjs +93 -0
  106. package/fesm2022/hyalo-angular-scroll-area.mjs.map +1 -0
  107. package/fesm2022/hyalo-angular-scroll-to-top.mjs +127 -0
  108. package/fesm2022/hyalo-angular-scroll-to-top.mjs.map +1 -0
  109. package/fesm2022/hyalo-angular-segmented.mjs +1 -1
  110. package/fesm2022/hyalo-angular-segmented.mjs.map +1 -1
  111. package/fesm2022/hyalo-angular-select.mjs +112 -15
  112. package/fesm2022/hyalo-angular-select.mjs.map +1 -1
  113. package/fesm2022/hyalo-angular-sidebar.mjs +241 -0
  114. package/fesm2022/hyalo-angular-sidebar.mjs.map +1 -0
  115. package/fesm2022/hyalo-angular-skeleton.mjs +131 -0
  116. package/fesm2022/hyalo-angular-skeleton.mjs.map +1 -0
  117. package/fesm2022/hyalo-angular-sparkline.mjs +110 -0
  118. package/fesm2022/hyalo-angular-sparkline.mjs.map +1 -0
  119. package/fesm2022/hyalo-angular-split-text.mjs +126 -0
  120. package/fesm2022/hyalo-angular-split-text.mjs.map +1 -0
  121. package/fesm2022/hyalo-angular-stat.mjs +193 -0
  122. package/fesm2022/hyalo-angular-stat.mjs.map +1 -0
  123. package/fesm2022/hyalo-angular-stepper.mjs +254 -0
  124. package/fesm2022/hyalo-angular-stepper.mjs.map +1 -0
  125. package/fesm2022/hyalo-angular-table.mjs +335 -0
  126. package/fesm2022/hyalo-angular-table.mjs.map +1 -0
  127. package/fesm2022/hyalo-angular-tabs.mjs +1 -1
  128. package/fesm2022/hyalo-angular-tabs.mjs.map +1 -1
  129. package/fesm2022/hyalo-angular-theme.mjs +1 -1
  130. package/fesm2022/hyalo-angular-theme.mjs.map +1 -1
  131. package/fesm2022/hyalo-angular-timeline.mjs +157 -0
  132. package/fesm2022/hyalo-angular-timeline.mjs.map +1 -0
  133. package/fesm2022/hyalo-angular-toast.mjs +2 -1
  134. package/fesm2022/hyalo-angular-toast.mjs.map +1 -1
  135. package/fesm2022/hyalo-angular.mjs +2 -473
  136. package/package.json +198 -2
  137. package/styles/parts/field.css +44 -36
  138. package/styles/parts/glass.css +2 -0
  139. package/styles/parts/motion.css +19 -0
  140. package/styles/parts/typography.css +17 -0
  141. package/types/hyalo-angular-accordion.d.ts +1 -1
  142. package/types/hyalo-angular-alert.d.ts +47 -0
  143. package/types/hyalo-angular-aspect-ratio.d.ts +13 -0
  144. package/types/hyalo-angular-avatar.d.ts +39 -0
  145. package/types/hyalo-angular-badge.d.ts +82 -0
  146. package/types/hyalo-angular-bento.d.ts +25 -0
  147. package/types/hyalo-angular-blocks.d.ts +272 -0
  148. package/types/hyalo-angular-border-beam.d.ts +15 -0
  149. package/types/hyalo-angular-breadcrumb.d.ts +22 -0
  150. package/types/hyalo-angular-button-group.d.ts +19 -0
  151. package/types/hyalo-angular-button.d.ts +4 -3
  152. package/types/hyalo-angular-card.d.ts +1 -1
  153. package/types/hyalo-angular-carousel.d.ts +147 -0
  154. package/types/hyalo-angular-chapter-nav.d.ts +79 -0
  155. package/types/hyalo-angular-chart.d.ts +90 -0
  156. package/types/hyalo-angular-code-block.d.ts +46 -0
  157. package/types/hyalo-angular-command.d.ts +41 -0
  158. package/types/hyalo-angular-copy.d.ts +39 -0
  159. package/types/hyalo-angular-core.d.ts +210 -0
  160. package/types/hyalo-angular-description-list.d.ts +16 -0
  161. package/types/hyalo-angular-dialog.d.ts +2 -1
  162. package/types/hyalo-angular-divider.d.ts +12 -0
  163. package/types/hyalo-angular-empty-state.d.ts +30 -0
  164. package/types/hyalo-angular-field.d.ts +10 -4
  165. package/types/hyalo-angular-filter.d.ts +122 -0
  166. package/types/hyalo-angular-hotspot.d.ts +70 -0
  167. package/types/hyalo-angular-hover-card.d.ts +47 -0
  168. package/types/hyalo-angular-image-compare.d.ts +55 -0
  169. package/types/hyalo-angular-kbd.d.ts +5 -0
  170. package/types/hyalo-angular-lightbox.d.ts +67 -0
  171. package/types/hyalo-angular-link.d.ts +5 -0
  172. package/types/hyalo-angular-list.d.ts +30 -0
  173. package/types/hyalo-angular-marquee.d.ts +48 -0
  174. package/types/hyalo-angular-menu.d.ts +105 -0
  175. package/types/hyalo-angular-mesh.d.ts +36 -0
  176. package/types/hyalo-angular-motion.d.ts +218 -0
  177. package/types/hyalo-angular-navigation-menu.d.ts +47 -0
  178. package/types/hyalo-angular-number-ticker.d.ts +52 -0
  179. package/types/hyalo-angular-overlay.d.ts +9 -0
  180. package/types/hyalo-angular-pagination.d.ts +59 -0
  181. package/types/hyalo-angular-popover.d.ts +10 -0
  182. package/types/hyalo-angular-progress.d.ts +46 -0
  183. package/types/hyalo-angular-progressive-blur.d.ts +14 -0
  184. package/types/hyalo-angular-refraction.d.ts +46 -0
  185. package/types/hyalo-angular-scroll-area.d.ts +18 -0
  186. package/types/hyalo-angular-scroll-to-top.d.ts +31 -0
  187. package/types/hyalo-angular-segmented.d.ts +1 -1
  188. package/types/hyalo-angular-select.d.ts +49 -3
  189. package/types/hyalo-angular-sidebar.d.ts +57 -0
  190. package/types/hyalo-angular-skeleton.d.ts +34 -0
  191. package/types/hyalo-angular-sparkline.d.ts +19 -0
  192. package/types/hyalo-angular-split-text.d.ts +24 -0
  193. package/types/hyalo-angular-stat.d.ts +56 -0
  194. package/types/hyalo-angular-stepper.d.ts +63 -0
  195. package/types/hyalo-angular-table.d.ts +125 -0
  196. package/types/hyalo-angular-timeline.d.ts +36 -0
  197. package/types/hyalo-angular.d.ts +2 -345
  198. package/fesm2022/hyalo-angular.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"hyalo-angular-dialog.mjs","names":["i1.HyDialogTitle","i1.HyDialogContent","i1.HyDialogActions","i1.HyDialogClose"],"sources":["../../../projects/hyalo/dialog/dialog-ref.ts","../../../projects/hyalo/dialog/dialog-parts.ts","../../../projects/hyalo/dialog/sheet.ts","../../../projects/hyalo/dialog/open-surface.ts","../../../projects/hyalo/dialog/dialog.ts","../../../projects/hyalo/dialog/dialog.html","../../../projects/hyalo/dialog/drawer.ts"],"sourcesContent":["import { DialogRef } from '@angular/cdk/dialog';\r\nimport { InjectionToken } from '@angular/core';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { MOTION } from '@hyalo/angular';\r\n\r\n/** Data passed to a dialog or drawer through `open(..., { data })`. */\r\nexport const HY_DIALOG_DATA = new InjectionToken<unknown>('HY_DIALOG_DATA');\r\n\r\n/**\r\n * Handle to an open dialog or drawer. Inject it in the content component to\r\n * close it, or keep the one `open()` returns.\r\n */\r\nexport class HyDialogRef<R = unknown> {\r\n private closing = false;\r\n\r\n /** Resolves with the result once the surface has closed. */\r\n readonly closed: Promise<R | undefined>;\r\n\r\n /**\r\n * @internal Set by surfaces that drive their own exit, like a sheet on a\r\n * spring. Calls `finish` once the surface is out of view.\r\n */\r\n exit: ((finish: () => void) => void) | null = null;\r\n\r\n /** @internal */\r\n constructor(private readonly cdkRef: DialogRef<R>) {\r\n this.closed = firstValueFrom(cdkRef.closed, { defaultValue: undefined });\r\n }\r\n\r\n /** Id of the dialog container element. */\r\n get id(): string {\r\n return this.cdkRef.id;\r\n }\r\n\r\n /** The element with `role=\"dialog\"`. */\r\n get containerElement(): HTMLElement | null {\r\n return this.cdkRef.overlayRef.overlayElement?.querySelector('.cdk-dialog-container') ?? null;\r\n }\r\n\r\n /**\r\n * Plays the exit animation, then closes. With reduced motion the exit is\r\n * a short fade. Calling it again while the animation runs does nothing.\r\n */\r\n close(result?: R): void {\r\n if (this.closing) return;\r\n this.closing = true;\r\n if (this.exit) {\r\n this.exit(() => this.cdkRef.close(result));\r\n return;\r\n }\r\n const pane = this.cdkRef.overlayRef.overlayElement;\r\n const backdrop = this.cdkRef.overlayRef.backdropElement;\r\n // The animation runs on the panel inside the pane.\r\n const panel = this.containerElement;\r\n pane.dataset['state'] = 'closing';\r\n backdrop?.setAttribute('data-state', 'closing');\r\n // The timeout is a safety net in case animationend never fires.\r\n let done = false;\r\n const finish = (): void => {\r\n if (done) return;\r\n done = true;\r\n pane.removeEventListener('animationend', onEnd);\r\n this.cdkRef.close(result);\r\n };\r\n // Ignore animations that bubble up from the content, like a button ripple.\r\n const onEnd = (event: Event): void => {\r\n if (event.target === pane || event.target === panel) finish();\r\n };\r\n pane.addEventListener('animationend', onEnd);\r\n setTimeout(finish, MOTION.settle.duration * 1000 + 80);\r\n }\r\n\r\n /**\r\n * @internal A sheet grabbed while it was closing stays open, and a later\r\n * `close()` works again.\r\n */\r\n cancelClose(): void {\r\n this.closing = false;\r\n }\r\n}\r\n","import { Directive, ElementRef, afterNextRender, inject, input } from '@angular/core';\r\nimport { injectId } from '@hyalo/angular';\r\n\r\nimport { HyDialogRef } from './dialog-ref';\r\n\r\n/**\r\n * The dialog or drawer heading. Its id becomes the container's\r\n * `aria-labelledby`, so screen readers announce it on open.\r\n */\r\n@Directive({\r\n selector: '[hyDialogTitle]',\r\n host: { class: 'hy-dialog__title', '[id]': 'id' },\r\n})\r\nexport class HyDialogTitle {\r\n protected readonly id = injectId('dialog-title');\r\n\r\n constructor() {\r\n const el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n afterNextRender(() =>\r\n el.closest('[role=\"dialog\"], [role=\"alertdialog\"]')?.setAttribute('aria-labelledby', this.id),\r\n );\r\n }\r\n}\r\n\r\n/** The scrollable body. */\r\n@Directive({ selector: '[hyDialogContent]', host: { class: 'hy-dialog__content' } })\r\nexport class HyDialogContent {}\r\n\r\n/** The button row at the bottom. Primary action goes last. */\r\n@Directive({ selector: '[hyDialogActions]', host: { class: 'hy-dialog__actions' } })\r\nexport class HyDialogActions {}\r\n\r\n/** Closes the surrounding dialog or drawer with an optional result. */\r\n@Directive({\r\n selector: 'button[hyDialogClose]',\r\n host: { type: 'button', '(click)': 'ref?.close(hyDialogClose())' },\r\n})\r\nexport class HyDialogClose {\r\n protected readonly ref = inject(HyDialogRef, { optional: true });\r\n /** The result to close with. A bare attribute closes with `undefined`. */\r\n readonly hyDialogClose = input<unknown, unknown>(undefined, {\r\n transform: (value) => (value === '' ? undefined : value),\r\n });\r\n}\r\n\r\n/** Everything needed to lay out dialog or drawer content. */\r\nexport const HY_DIALOG_PARTS = [\r\n HyDialogTitle,\r\n HyDialogContent,\r\n HyDialogActions,\r\n HyDialogClose,\r\n] as const;\r\n","import { HySpring, HyVelocityTracker, project, rubberband, SPRINGS } from '@hyalo/angular';\r\nimport type { HyDrawerSide } from './drawer';\r\n\r\n/** Movement before a press turns into a drag, in px. */\r\nconst SLOP = 10;\r\n/** Presses on these stay presses: they never start a drag. */\r\nconst INTERACTIVE =\r\n 'button, a[href], input, select, textarea, label, summary, [contenteditable], [role=\"slider\"], [tabindex]:not([tabindex=\"-1\"])';\r\n\r\n/** @internal What a drawer needs from its HyDialogRef. */\r\nexport interface HySheetHost {\r\n readonly dismissible: boolean;\r\n close(): void;\r\n cancelClose(): void;\r\n}\r\n\r\n/**\r\n * @internal Puts a drawer or bottom sheet on a spring and lets people drag\r\n * it toward its edge to close it.\r\n *\r\n * - Enter and exit run on the same spring, so the panel can be grabbed at\r\n * any moment, even while it is closing, and it follows from where it is.\r\n * - The drag tracks the pointer 1:1. Pulling the wrong way rubber-bands.\r\n * - On release the flick is projected forward, and the panel springs to\r\n * whichever end the projection lands nearer, carrying the finger's speed.\r\n * - The backdrop dims in step with how open the panel is.\r\n *\r\n * Returns the exit for `HyDialogRef.exit`.\r\n */\r\nexport function driveSheet(\r\n panel: HTMLElement,\r\n backdrop: HTMLElement | null,\r\n side: HyDrawerSide,\r\n host: HySheetHost,\r\n): (finish: () => void) => void {\r\n const vertical = side === 'bottom';\r\n const rtl = getComputedStyle(panel).direction === 'rtl';\r\n // +1 when closing moves toward larger x or y.\r\n const sign = vertical ? 1 : (side === 'end') !== rtl ? 1 : -1;\r\n // Extra travel so the shadow is gone too.\r\n const size = (): number => (vertical ? panel.offsetHeight : panel.offsetWidth) + 32;\r\n\r\n panel.classList.add('hy-sheet-driven');\r\n if (backdrop) backdrop.style.transition = 'none';\r\n\r\n /** `offset` is how far the panel has moved out, in px. 0 is open. */\r\n const paint = (offset: number): void => {\r\n const full = size();\r\n // Past the open position, and past closed when it may not close, the\r\n // panel resists instead of following.\r\n let shown = offset < 0 ? rubberband(offset, full) : offset;\r\n if (!host.dismissible && offset > 0) shown = rubberband(offset, full);\r\n const px = `${shown * sign}px`;\r\n panel.style.translate = vertical ? `0 ${px}` : `${px} 0`;\r\n if (backdrop) backdrop.style.opacity = String(Math.min(1, Math.max(0, 1 - shown / full)));\r\n };\r\n\r\n const spring = new HySpring(0, paint);\r\n // Start out of view without measuring yet; the content has not rendered.\r\n panel.style.translate = vertical ? '0 100%' : `${sign * 100}% 0`;\r\n if (backdrop) backdrop.style.opacity = '0';\r\n requestAnimationFrame(() => {\r\n spring.set(size());\r\n spring.to(0, SPRINGS.settle);\r\n });\r\n\r\n let closing = false;\r\n const exit = (finish: () => void): void => {\r\n // A hidden page runs no animation frames, so the spring would never\r\n // arrive and `closed` would never resolve.\r\n if (panel.ownerDocument.hidden) {\r\n spring.stop();\r\n finish();\r\n return;\r\n }\r\n closing = true;\r\n spring.to(size(), { ...SPRINGS.settle, onRest: finish });\r\n };\r\n\r\n // Touch scrolling and our drag must not fight. Side drawers drag across\r\n // the scroll direction. A sheet only takes vertical touches when its\r\n // content cannot scroll; otherwise it is dragged by the grabber.\r\n if (vertical) {\r\n const grabber = panel.ownerDocument.createElement('div');\r\n grabber.className = 'hy-drawer__grabber';\r\n grabber.setAttribute('aria-hidden', 'true');\r\n panel.prepend(grabber);\r\n if (typeof ResizeObserver === 'function') {\r\n new ResizeObserver(() => {\r\n panel.style.touchAction = panel.scrollHeight > panel.clientHeight + 1 ? '' : 'none';\r\n }).observe(panel);\r\n }\r\n }\r\n\r\n interface Press {\r\n readonly id: number;\r\n x: number;\r\n readonly y: number;\r\n from: number;\r\n dragging: boolean;\r\n }\r\n let press: Press | null = null;\r\n const tracker = new HyVelocityTracker();\r\n const along = (e: PointerEvent): number => (vertical ? e.clientY : e.clientX) * sign;\r\n const across = (e: PointerEvent): number => (vertical ? e.clientX : e.clientY);\r\n\r\n const grab = (p: Press, e: PointerEvent): void => {\r\n p.dragging = true;\r\n p.x = along(e);\r\n p.from = spring.value;\r\n spring.stop();\r\n if (closing) {\r\n // Taken back mid-exit: the sheet stays, and close() can run again.\r\n closing = false;\r\n host.cancelClose();\r\n }\r\n tracker.reset();\r\n tracker.add(spring.value);\r\n try {\r\n panel.setPointerCapture(e.pointerId);\r\n } catch {\r\n // The pointer is already gone, as when it lifted on the same frame.\r\n }\r\n panel.dataset['dragging'] = '';\r\n panel.ownerDocument.getSelection()?.removeAllRanges();\r\n };\r\n\r\n panel.addEventListener('pointerdown', (e) => {\r\n if (e.button !== 0 || !e.isPrimary) return;\r\n const target = e.target as Element;\r\n const onGrabber = !!target.closest('.hy-drawer__grabber');\r\n if (!onGrabber && target.closest(INTERACTIVE)) return;\r\n if (vertical && !onGrabber && panel.scrollTop > 0) return;\r\n const p: Press = {\r\n id: e.pointerId,\r\n x: along(e),\r\n y: across(e),\r\n from: spring.value,\r\n dragging: false,\r\n };\r\n press = p;\r\n // A panel already in motion is caught right away, with no slop.\r\n if (spring.running) grab(p, e);\r\n });\r\n\r\n panel.addEventListener('pointermove', (e) => {\r\n if (!press || e.pointerId !== press.id) return;\r\n const moved = along(e) - press.x;\r\n if (!press.dragging) {\r\n const cross = Math.abs(across(e) - press.y);\r\n if (cross > SLOP && cross > Math.abs(moved)) {\r\n press = null;\r\n return;\r\n }\r\n if (Math.abs(moved) < SLOP) return;\r\n grab(press, e);\r\n return;\r\n }\r\n const offset = press.from + moved;\r\n tracker.add(offset);\r\n spring.set(offset);\r\n });\r\n\r\n const release = (e: PointerEvent): void => {\r\n if (!press || e.pointerId !== press.id) return;\r\n const wasDragging = press.dragging;\r\n press = null;\r\n if (!wasDragging) return;\r\n delete panel.dataset['dragging'];\r\n // A drag must not end in a click on whatever is under the pointer.\r\n const swallow = (click: Event): void => {\r\n click.stopPropagation();\r\n click.preventDefault();\r\n };\r\n panel.addEventListener('click', swallow, { capture: true, once: true });\r\n setTimeout(() => panel.removeEventListener('click', swallow, { capture: true }));\r\n\r\n const velocity = e.type === 'pointercancel' ? 0 : tracker.velocity();\r\n const full = size();\r\n const landing = spring.value + project(velocity);\r\n // A clear flick decides by its direction, a slow release by where it lands.\r\n const out = Math.abs(velocity) > 400 ? velocity > 0 : landing > full / 2;\r\n spring.velocity = velocity;\r\n if (out && host.dismissible) host.close();\r\n else spring.to(0, SPRINGS.settle);\r\n };\r\n panel.addEventListener('pointerup', release);\r\n panel.addEventListener('pointercancel', release);\r\n\r\n return exit;\r\n}\r\n","import { Dialog, type DialogConfig } from '@angular/cdk/dialog';\r\nimport type { ComponentType } from '@angular/cdk/portal';\r\nimport type { PositionStrategy } from '@angular/cdk/overlay';\r\nimport type { TemplateRef } from '@angular/core';\r\nimport { filter } from 'rxjs';\r\nimport type { HyFidelity, HyMaterial, HyMotion } from '@hyalo/angular';\r\nimport { HY_DIALOG_DATA, HyDialogRef } from './dialog-ref';\r\nimport type { HyDrawerSide } from './drawer';\r\nimport { driveSheet } from './sheet';\r\n\r\n/** Options shared by dialogs and drawers. */\r\nexport interface HySurfaceConfig<D> {\r\n /** Passed to the content as `HY_DIALOG_DATA`. */\r\n readonly data?: D;\r\n /** Accessible name, when the content has no `hyDialogTitle`. */\r\n readonly label?: string;\r\n /** Close on Escape and backdrop click. Defaults to true. */\r\n readonly dismissible?: boolean;\r\n /** Glass material of the panel. */\r\n readonly material?: HyMaterial;\r\n /** Where focus goes on open. Defaults to the first tabbable element. */\r\n readonly autoFocus?: DialogConfig['autoFocus'];\r\n /** `alertdialog` for messages that need an answer. */\r\n readonly role?: 'dialog' | 'alertdialog';\r\n}\r\n\r\n/** @internal Opens a CDK dialog wrapped in a HyDialogRef. */\r\nexport function openSurface<R, D>(\r\n cdk: Dialog,\r\n motion: HyMotion,\r\n fidelity: HyFidelity,\r\n content: ComponentType<unknown> | TemplateRef<unknown>,\r\n config: HySurfaceConfig<D>,\r\n extra: {\r\n panelClass: string[];\r\n positionStrategy?: PositionStrategy;\r\n width?: string;\r\n maxWidth?: string;\r\n height?: string;\r\n /** Drawers and sheets run on a spring and can be dragged closed. */\r\n sheet?: HyDrawerSide;\r\n },\r\n): HyDialogRef<R> {\r\n let ref: HyDialogRef<R> | undefined;\r\n const dismissible = config.dismissible ?? true;\r\n\r\n const cdkRef = cdk.open<R, D, unknown>(content, {\r\n data: config.data,\r\n role: config.role ?? 'dialog',\r\n ariaLabel: config.label ?? null,\r\n autoFocus: config.autoFocus ?? 'first-tabbable',\r\n restoreFocus: true,\r\n ariaModal: true,\r\n // Closing is handled here so the exit animation can play first.\r\n disableClose: true,\r\n hasBackdrop: true,\r\n backdropClass: 'hy-backdrop',\r\n panelClass: extra.panelClass,\r\n positionStrategy: extra.positionStrategy,\r\n width: extra.width,\r\n maxWidth: extra.maxWidth,\r\n height: extra.height,\r\n providers: (dialogRef) => {\r\n ref = new HyDialogRef<R>(dialogRef);\r\n return [\r\n { provide: HyDialogRef, useValue: ref },\r\n { provide: HY_DIALOG_DATA, useValue: config.data },\r\n ];\r\n },\r\n });\r\n\r\n const hyRef = ref ?? new HyDialogRef<R>(cdkRef);\r\n const container = hyRef.containerElement;\r\n if (container) {\r\n container.classList.add('hy-glass');\r\n container.dataset['material'] =\r\n fidelity.tier() === 'low' ? 'solid' : (config.material ?? 'frosted');\r\n // Dialogs and sheets are the largest glass on the page, so the thickest.\r\n container.dataset['thickness'] = 'thick';\r\n // With reduced motion the CSS cross-fade runs instead of the spring.\r\n if (extra.sheet && !motion.reduced()) {\r\n hyRef.exit = driveSheet(container, cdkRef.overlayRef.backdropElement, extra.sheet, {\r\n dismissible,\r\n close: () => hyRef.close(),\r\n cancelClose: () => hyRef.cancelClose(),\r\n });\r\n }\r\n }\r\n if (dismissible) {\r\n cdkRef.backdropClick.subscribe(() => hyRef.close());\r\n cdkRef.keydownEvents\r\n .pipe(filter((e) => e.key === 'Escape' && !e.defaultPrevented))\r\n .subscribe((e) => {\r\n e.preventDefault();\r\n hyRef.close();\r\n });\r\n }\r\n return hyRef;\r\n}\r\n","import { Dialog } from '@angular/cdk/dialog';\r\nimport type { ComponentType } from '@angular/cdk/portal';\r\nimport { ChangeDetectionStrategy, Component, Injectable, TemplateRef, inject } from '@angular/core';\r\nimport { HyButton } from '@hyalo/angular/button';\r\n\r\nimport { HyFidelity, HyMotion, type HyTone } from '@hyalo/angular';\r\n\r\nimport { HY_DIALOG_DATA, HyDialogRef } from './dialog-ref';\r\nimport { HY_DIALOG_PARTS } from './dialog-parts';\r\nimport { openSurface, type HySurfaceConfig } from './open-surface';\r\n\r\n/** Dialog width. `full` fills the screen on small viewports. */\r\nexport type HyDialogSize = 'sm' | 'md' | 'lg' | 'full';\r\n\r\n// Set inline because the CDK pane's own max-width sits outside our cascade layers.\r\nconst MAX_WIDTH: Record<HyDialogSize, string> = {\r\n sm: '26rem',\r\n md: '36rem',\r\n lg: '52rem',\r\n full: '72rem',\r\n};\r\n\r\n/** Options for {@link HyDialog.open}. */\r\nexport interface HyDialogConfig<D = unknown> extends HySurfaceConfig<D> {\r\n readonly size?: HyDialogSize;\r\n}\r\n\r\n/** Options for {@link HyDialog.confirm}. */\r\nexport interface HyConfirmOptions {\r\n readonly title: string;\r\n readonly message?: string;\r\n readonly confirmLabel?: string;\r\n readonly cancelLabel?: string;\r\n /** Use `danger` for destructive actions. */\r\n readonly tone?: HyTone;\r\n}\r\n\r\n@Component({\r\n selector: 'hy-confirm-dialog',\r\n imports: [HY_DIALOG_PARTS, HyButton],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './dialog.html',\r\n})\r\nclass HyConfirmDialog {\r\n protected readonly data = inject(HY_DIALOG_DATA) as HyConfirmOptions;\r\n}\r\n\r\n/**\r\n * Opens modal dialogs. Focus is trapped inside while open and returns to\r\n * the element that opened it. Escape and a backdrop click close it unless\r\n * `dismissible` is false.\r\n *\r\n * ```ts\r\n * const ref = this.dialog.open(EditAddress, { data: address, size: 'md' });\r\n * const saved = await ref.closed;\r\n *\r\n * if (await this.dialog.confirm({ title: 'Delete this draft?', tone: 'danger', confirmLabel: 'Delete' })) {\r\n * ...\r\n * }\r\n * ```\r\n *\r\n * In the content component, inject `HyDialogRef` to close and\r\n * `HY_DIALOG_DATA` to read the data. Lay it out with `hyDialogTitle`,\r\n * `hyDialogContent` and `hyDialogActions`.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class HyDialog {\r\n private readonly cdk = inject(Dialog);\r\n private readonly motion = inject(HyMotion);\r\n private readonly fidelity = inject(HyFidelity);\r\n\r\n /** Opens a component or template as a dialog. */\r\n open<R = unknown, D = unknown>(\r\n content: ComponentType<unknown> | TemplateRef<unknown>,\r\n config: HyDialogConfig<D> = {},\r\n ): HyDialogRef<R> {\r\n const size = config.size ?? 'md';\r\n return openSurface<R, D>(this.cdk, this.motion, this.fidelity, content, config, {\r\n panelClass: ['hy-dialog-pane', `hy-dialog--${size}`],\r\n maxWidth: MAX_WIDTH[size],\r\n });\r\n }\r\n\r\n /** Asks a yes or no question. Resolves to true only when confirmed. */\r\n async confirm(options: HyConfirmOptions): Promise<boolean> {\r\n const ref = this.open<boolean, HyConfirmOptions>(HyConfirmDialog, {\r\n data: options,\r\n size: 'sm',\r\n role: 'alertdialog',\r\n });\r\n return (await ref.closed) === true;\r\n }\r\n}\r\n","<h2 hyDialogTitle>{{ data.title }}</h2>\r\n@if (data.message) {\r\n <p hyDialogContent>{{ data.message }}</p>\r\n}\r\n<div hyDialogActions>\r\n <button hyButton variant=\"ghost\" tone=\"neutral\" [hyDialogClose]=\"false\">\r\n {{ data.cancelLabel ?? 'Cancel' }}\r\n </button>\r\n <button hyButton [tone]=\"data.tone ?? 'primary'\" [hyDialogClose]=\"true\">\r\n {{ data.confirmLabel ?? 'Confirm' }}\r\n </button>\r\n</div>\r\n","import { Dialog } from '@angular/cdk/dialog';\r\nimport { createGlobalPositionStrategy } from '@angular/cdk/overlay';\r\nimport type { ComponentType } from '@angular/cdk/portal';\r\nimport { Injectable, Injector, TemplateRef, inject } from '@angular/core';\r\nimport { HyFidelity, HyMotion } from '@hyalo/angular';\r\nimport type { HyDialogRef } from './dialog-ref';\r\nimport { openSurface, type HySurfaceConfig } from './open-surface';\r\n\r\n/**\r\n * Which edge the drawer slides from. `start` and `end` follow the text\r\n * direction, so `end` is the right edge in LTR and the left edge in RTL.\r\n * `bottom` gives a sheet, handy on phones.\r\n */\r\nexport type HyDrawerSide = 'start' | 'end' | 'bottom';\r\n\r\n/** Options for {@link HyDrawer.open}. */\r\nexport interface HyDrawerConfig<D = unknown> extends HySurfaceConfig<D> {\r\n readonly side?: HyDrawerSide;\r\n /** Any CSS length. Width for side drawers, height for the bottom sheet. */\r\n readonly size?: string;\r\n}\r\n\r\n/**\r\n * Opens a modal drawer: navigation on phones, a cart, filters. It behaves\r\n * like a dialog (focus trap, Escape, backdrop, focus restore) and uses the\r\n * same content parts and `HyDialogRef`.\r\n *\r\n * It runs on a spring and follows the pointer: drag it toward its edge, or\r\n * flick it, to close it, and grab it again while it moves. A bottom sheet\r\n * shows a grabber. With reduced motion it cross-fades instead.\r\n *\r\n * ```ts\r\n * this.drawer.open(CartPanel, { side: 'end', label: 'Cart' });\r\n * ```\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class HyDrawer {\r\n private readonly cdk = inject(Dialog);\r\n private readonly motion = inject(HyMotion);\r\n private readonly fidelity = inject(HyFidelity);\r\n private readonly injector = inject(Injector);\r\n\r\n /** Opens a component or template in a drawer. */\r\n open<R = unknown, D = unknown>(\r\n content: ComponentType<unknown> | TemplateRef<unknown>,\r\n config: HyDrawerConfig<D> = {},\r\n ): HyDialogRef<R> {\r\n const side = config.side ?? 'end';\r\n const position = createGlobalPositionStrategy(this.injector);\r\n if (side === 'bottom') position.bottom('0').centerHorizontally();\r\n else if (side === 'start') position.start('0').top('0');\r\n else position.end('0').top('0');\r\n\r\n return openSurface<R, D>(this.cdk, this.motion, this.fidelity, content, config, {\r\n panelClass: ['hy-drawer-pane', `hy-drawer--${side}`],\r\n positionStrategy: position,\r\n width: side === 'bottom' ? '100%' : (config.size ?? 'min(24rem, 100vw - 2.5rem)'),\r\n height: side === 'bottom' ? (config.size ?? 'auto') : '100%',\r\n sheet: side,\r\n });\r\n }\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"hyalo-angular-dialog.mjs","names":["i1.HyDialogTitle","i1.HyDialogContent","i1.HyDialogActions","i1.HyDialogClose"],"sources":["../../../projects/hyalo/dialog/dialog-ref.ts","../../../projects/hyalo/dialog/dialog-parts.ts","../../../projects/hyalo/dialog/sheet.ts","../../../projects/hyalo/dialog/open-surface.ts","../../../projects/hyalo/dialog/dialog.ts","../../../projects/hyalo/dialog/dialog.html","../../../projects/hyalo/dialog/drawer.ts"],"sourcesContent":["import { DialogRef } from '@angular/cdk/dialog';\r\nimport { InjectionToken } from '@angular/core';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport { MOTION } from '@hyalo/angular/motion';\r\n\r\n/** Data passed to a dialog or drawer through `open(..., { data })`. */\r\nexport const HY_DIALOG_DATA = new InjectionToken<unknown>('HY_DIALOG_DATA');\r\n\r\n/**\r\n * Handle to an open dialog or drawer. Inject it in the content component to\r\n * close it, or keep the one `open()` returns.\r\n */\r\nexport class HyDialogRef<R = unknown> {\r\n private closing = false;\r\n\r\n /** Resolves with the result once the surface has closed. */\r\n readonly closed: Promise<R | undefined>;\r\n\r\n /**\r\n * @internal Set by surfaces that drive their own exit, like a sheet on a\r\n * spring. Calls `finish` once the surface is out of view.\r\n */\r\n exit: ((finish: () => void) => void) | null = null;\r\n\r\n /** @internal */\r\n constructor(private readonly cdkRef: DialogRef<R>) {\r\n this.closed = firstValueFrom(cdkRef.closed, { defaultValue: undefined });\r\n }\r\n\r\n /** Id of the dialog container element. */\r\n get id(): string {\r\n return this.cdkRef.id;\r\n }\r\n\r\n /** The element with `role=\"dialog\"`. */\r\n get containerElement(): HTMLElement | null {\r\n return this.cdkRef.overlayRef.overlayElement?.querySelector('.cdk-dialog-container') ?? null;\r\n }\r\n\r\n /**\r\n * Plays the exit animation, then closes. With reduced motion the exit is\r\n * a short fade. Calling it again while the animation runs does nothing.\r\n */\r\n close(result?: R): void {\r\n if (this.closing) return;\r\n this.closing = true;\r\n if (this.exit) {\r\n this.exit(() => this.cdkRef.close(result));\r\n return;\r\n }\r\n const pane = this.cdkRef.overlayRef.overlayElement;\r\n const backdrop = this.cdkRef.overlayRef.backdropElement;\r\n // The animation runs on the panel inside the pane.\r\n const panel = this.containerElement;\r\n pane.dataset['state'] = 'closing';\r\n backdrop?.setAttribute('data-state', 'closing');\r\n // The timeout is a safety net in case animationend never fires.\r\n let done = false;\r\n const finish = (): void => {\r\n if (done) return;\r\n done = true;\r\n pane.removeEventListener('animationend', onEnd);\r\n this.cdkRef.close(result);\r\n };\r\n // Ignore animations that bubble up from the content, like a button ripple.\r\n const onEnd = (event: Event): void => {\r\n if (event.target === pane || event.target === panel) finish();\r\n };\r\n pane.addEventListener('animationend', onEnd);\r\n setTimeout(finish, MOTION.settle.duration * 1000 + 80);\r\n }\r\n\r\n /**\r\n * @internal A sheet grabbed while it was closing stays open, and a later\r\n * `close()` works again.\r\n */\r\n cancelClose(): void {\r\n this.closing = false;\r\n }\r\n}\r\n","import { Directive, ElementRef, afterNextRender, inject, input } from '@angular/core';\r\nimport { injectId } from '@hyalo/angular/core';\r\n\r\nimport { HyDialogRef } from './dialog-ref';\r\n\r\n/**\r\n * The dialog or drawer heading. Its id becomes the container's\r\n * `aria-labelledby`, so screen readers announce it on open.\r\n */\r\n@Directive({\r\n selector: '[hyDialogTitle]',\r\n host: { class: 'hy-dialog__title', '[id]': 'id' },\r\n})\r\nexport class HyDialogTitle {\r\n protected readonly id = injectId('dialog-title');\r\n\r\n constructor() {\r\n const el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\r\n afterNextRender(() =>\r\n el.closest('[role=\"dialog\"], [role=\"alertdialog\"]')?.setAttribute('aria-labelledby', this.id),\r\n );\r\n }\r\n}\r\n\r\n/** The scrollable body. */\r\n@Directive({ selector: '[hyDialogContent]', host: { class: 'hy-dialog__content' } })\r\nexport class HyDialogContent {}\r\n\r\n/** The button row at the bottom. Primary action goes last. */\r\n@Directive({ selector: '[hyDialogActions]', host: { class: 'hy-dialog__actions' } })\r\nexport class HyDialogActions {}\r\n\r\n/** Closes the surrounding dialog or drawer with an optional result. */\r\n@Directive({\r\n selector: 'button[hyDialogClose]',\r\n host: { type: 'button', '(click)': 'ref?.close(hyDialogClose())' },\r\n})\r\nexport class HyDialogClose {\r\n protected readonly ref = inject(HyDialogRef, { optional: true });\r\n /** The result to close with. A bare attribute closes with `undefined`. */\r\n readonly hyDialogClose = input<unknown, unknown>(undefined, {\r\n transform: (value) => (value === '' ? undefined : value),\r\n });\r\n}\r\n\r\n/** Everything needed to lay out dialog or drawer content. */\r\nexport const HY_DIALOG_PARTS = [\r\n HyDialogTitle,\r\n HyDialogContent,\r\n HyDialogActions,\r\n HyDialogClose,\r\n] as const;\r\n","import { HySpring, HyVelocityTracker, project, rubberband, SPRINGS } from '@hyalo/angular/motion';\r\nimport type { HyDrawerSide } from './drawer';\r\n\r\n/** Movement before a press turns into a drag, in px. */\r\nconst SLOP = 10;\r\n/** Presses on these stay presses: they never start a drag. */\r\nconst INTERACTIVE =\r\n 'button, a[href], input, select, textarea, label, summary, [contenteditable], [role=\"slider\"], [tabindex]:not([tabindex=\"-1\"])';\r\n\r\n/** @internal What a drawer needs from its HyDialogRef. */\r\nexport interface HySheetHost {\r\n readonly dismissible: boolean;\r\n close(): void;\r\n cancelClose(): void;\r\n}\r\n\r\n/**\r\n * @internal Puts a drawer or bottom sheet on a spring and lets people drag\r\n * it toward its edge to close it.\r\n *\r\n * - Enter and exit run on the same spring, so the panel can be grabbed at\r\n * any moment, even while it is closing, and it follows from where it is.\r\n * - The drag tracks the pointer 1:1. Pulling the wrong way rubber-bands.\r\n * - On release the flick is projected forward, and the panel springs to\r\n * whichever end the projection lands nearer, carrying the finger's speed.\r\n * - The backdrop dims in step with how open the panel is.\r\n *\r\n * Returns the exit animation and its lifecycle cleanup.\r\n */\r\nexport function driveSheet(\r\n panel: HTMLElement,\r\n backdrop: HTMLElement | null,\r\n side: HyDrawerSide,\r\n host: HySheetHost,\r\n): { exit: (finish: () => void) => void; destroy: () => void } {\r\n const lifetime = new (panel.ownerDocument.defaultView?.AbortController ?? AbortController)();\r\n let disposed = false;\r\n let resize: ResizeObserver | undefined;\r\n let clickTimer: ReturnType<typeof setTimeout> | undefined;\r\n const vertical = side === 'bottom';\r\n const rtl = getComputedStyle(panel).direction === 'rtl';\r\n // +1 when closing moves toward larger x or y.\r\n const sign = vertical ? 1 : (side === 'end') !== rtl ? 1 : -1;\r\n // Extra travel so the shadow is gone too.\r\n const size = (): number => (vertical ? panel.offsetHeight : panel.offsetWidth) + 32;\r\n\r\n panel.classList.add('hy-sheet-driven');\r\n if (backdrop) backdrop.style.transition = 'none';\r\n\r\n /** `offset` is how far the panel has moved out, in px. 0 is open. */\r\n const paint = (offset: number): void => {\r\n const full = size();\r\n // Past the open position, and past closed when it may not close, the\r\n // panel resists instead of following.\r\n let shown = offset < 0 ? rubberband(offset, full) : offset;\r\n if (!host.dismissible && offset > 0) shown = rubberband(offset, full);\r\n const px = `${shown * sign}px`;\r\n panel.style.translate = vertical ? `0 ${px}` : `${px} 0`;\r\n if (backdrop) backdrop.style.opacity = String(Math.min(1, Math.max(0, 1 - shown / full)));\r\n };\r\n\r\n const spring = new HySpring(0, paint);\r\n // Start out of view without measuring yet; the content has not rendered.\r\n panel.style.translate = vertical ? '0 100%' : `${sign * 100}% 0`;\r\n if (backdrop) backdrop.style.opacity = '0';\r\n let enterFrame = requestAnimationFrame(() => {\r\n enterFrame = 0;\r\n spring.set(size());\r\n spring.to(0, SPRINGS.settle);\r\n });\r\n\r\n let closing = false;\r\n const exit = (finish: () => void): void => {\r\n cancelAnimationFrame(enterFrame);\r\n enterFrame = 0;\r\n // A hidden page runs no animation frames, so the spring would never\r\n // arrive and `closed` would never resolve.\r\n if (disposed || panel.ownerDocument.hidden) {\r\n spring.stop();\r\n finish();\r\n return;\r\n }\r\n closing = true;\r\n spring.to(size(), { ...SPRINGS.settle, onRest: finish });\r\n };\r\n\r\n // Touch scrolling and our drag must not fight. Side drawers drag across\r\n // the scroll direction. A sheet only takes vertical touches when its\r\n // content cannot scroll; otherwise it is dragged by the grabber.\r\n if (vertical) {\r\n const grabber = panel.ownerDocument.createElement('div');\r\n grabber.className = 'hy-drawer__grabber';\r\n grabber.setAttribute('aria-hidden', 'true');\r\n panel.prepend(grabber);\r\n if (typeof ResizeObserver === 'function') {\r\n resize = new ResizeObserver(() => {\r\n panel.style.touchAction = panel.scrollHeight > panel.clientHeight + 1 ? '' : 'none';\r\n });\r\n resize.observe(panel);\r\n }\r\n }\r\n\r\n interface Press {\r\n readonly id: number;\r\n x: number;\r\n readonly y: number;\r\n from: number;\r\n dragging: boolean;\r\n }\r\n let press: Press | null = null;\r\n const tracker = new HyVelocityTracker();\r\n const along = (e: PointerEvent): number => (vertical ? e.clientY : e.clientX) * sign;\r\n const across = (e: PointerEvent): number => (vertical ? e.clientX : e.clientY);\r\n\r\n const grab = (p: Press, e: PointerEvent): void => {\r\n p.dragging = true;\r\n p.x = along(e);\r\n p.from = spring.value;\r\n spring.stop();\r\n if (closing) {\r\n // Taken back mid-exit: the sheet stays, and close() can run again.\r\n closing = false;\r\n host.cancelClose();\r\n }\r\n tracker.reset();\r\n tracker.add(spring.value);\r\n try {\r\n panel.setPointerCapture(e.pointerId);\r\n } catch {\r\n // The pointer is already gone, as when it lifted on the same frame.\r\n }\r\n panel.dataset['dragging'] = '';\r\n panel.ownerDocument.getSelection()?.removeAllRanges();\r\n };\r\n\r\n panel.addEventListener(\r\n 'pointerdown',\r\n (e) => {\r\n if (e.button !== 0 || !e.isPrimary) return;\r\n const target = e.target as Element;\r\n const onGrabber = !!target.closest('.hy-drawer__grabber');\r\n if (!onGrabber && target.closest(INTERACTIVE)) return;\r\n if (vertical && !onGrabber && panel.scrollTop > 0) return;\r\n const p: Press = {\r\n id: e.pointerId,\r\n x: along(e),\r\n y: across(e),\r\n from: spring.value,\r\n dragging: false,\r\n };\r\n press = p;\r\n // A panel already in motion is caught right away, with no slop.\r\n if (spring.running) grab(p, e);\r\n },\r\n { signal: lifetime.signal },\r\n );\r\n\r\n panel.addEventListener(\r\n 'pointermove',\r\n (e) => {\r\n if (!press || e.pointerId !== press.id) return;\r\n const moved = along(e) - press.x;\r\n if (!press.dragging) {\r\n const cross = Math.abs(across(e) - press.y);\r\n if (cross > SLOP && cross > Math.abs(moved)) {\r\n press = null;\r\n return;\r\n }\r\n if (Math.abs(moved) < SLOP) return;\r\n grab(press, e);\r\n return;\r\n }\r\n const offset = press.from + moved;\r\n tracker.add(offset);\r\n spring.set(offset);\r\n },\r\n { signal: lifetime.signal },\r\n );\r\n\r\n const swallow = (click: Event): void => {\r\n click.stopPropagation();\r\n click.preventDefault();\r\n };\r\n const release = (e: PointerEvent): void => {\r\n if (!press || e.pointerId !== press.id) return;\r\n const wasDragging = press.dragging;\r\n press = null;\r\n if (!wasDragging) return;\r\n delete panel.dataset['dragging'];\r\n // A drag must not end in a click on whatever is under the pointer.\r\n panel.addEventListener('click', swallow, {\r\n capture: true,\r\n once: true,\r\n signal: lifetime.signal,\r\n });\r\n clearTimeout(clickTimer);\r\n clickTimer = setTimeout(() => panel.removeEventListener('click', swallow, { capture: true }));\r\n\r\n const velocity = e.type === 'pointercancel' ? 0 : tracker.velocity();\r\n const full = size();\r\n const landing = spring.value + project(velocity);\r\n // A clear flick decides by its direction, a slow release by where it lands.\r\n const out = Math.abs(velocity) > 400 ? velocity > 0 : landing > full / 2;\r\n spring.velocity = velocity;\r\n if (out && host.dismissible) host.close();\r\n else spring.to(0, SPRINGS.settle);\r\n };\r\n panel.addEventListener('pointerup', release, { signal: lifetime.signal });\r\n panel.addEventListener('pointercancel', release, { signal: lifetime.signal });\r\n\r\n return {\r\n exit,\r\n destroy: () => {\r\n if (disposed) return;\r\n disposed = true;\r\n cancelAnimationFrame(enterFrame);\r\n spring.stop();\r\n resize?.disconnect();\r\n lifetime.abort();\r\n clearTimeout(clickTimer);\r\n press = null;\r\n },\r\n };\r\n}\r\n","import { Dialog, type DialogConfig } from '@angular/cdk/dialog';\r\nimport type { ComponentType } from '@angular/cdk/portal';\r\nimport type { PositionStrategy } from '@angular/cdk/overlay';\r\nimport type { TemplateRef } from '@angular/core';\r\nimport { filter } from 'rxjs';\r\nimport type { HyFidelity, HyMaterial } from '@hyalo/angular/core';\r\nimport type { HyMotion } from '@hyalo/angular/motion';\r\nimport { HY_DIALOG_DATA, HyDialogRef } from './dialog-ref';\r\nimport type { HyDrawerSide } from './drawer';\r\nimport { driveSheet } from './sheet';\r\n\r\n/** Options shared by dialogs and drawers. */\r\nexport interface HySurfaceConfig<D> {\r\n /** Passed to the content as `HY_DIALOG_DATA`. */\r\n readonly data?: D;\r\n /** Accessible name, when the content has no `hyDialogTitle`. */\r\n readonly label?: string;\r\n /** Close on Escape and backdrop click. Defaults to true. */\r\n readonly dismissible?: boolean;\r\n /** Glass material of the panel. */\r\n readonly material?: HyMaterial;\r\n /** Where focus goes on open. Defaults to the first tabbable element. */\r\n readonly autoFocus?: DialogConfig['autoFocus'];\r\n /** `alertdialog` for messages that need an answer. */\r\n readonly role?: 'dialog' | 'alertdialog';\r\n}\r\n\r\n/** @internal Opens a CDK dialog wrapped in a HyDialogRef. */\r\nexport function openSurface<R, D>(\r\n cdk: Dialog,\r\n motion: HyMotion,\r\n fidelity: HyFidelity,\r\n content: ComponentType<unknown> | TemplateRef<unknown>,\r\n config: HySurfaceConfig<D>,\r\n extra: {\r\n panelClass: string[];\r\n positionStrategy?: PositionStrategy;\r\n width?: string;\r\n maxWidth?: string;\r\n height?: string;\r\n /** Drawers and sheets run on a spring and can be dragged closed. */\r\n sheet?: HyDrawerSide;\r\n },\r\n): HyDialogRef<R> {\r\n let ref: HyDialogRef<R> | undefined;\r\n const dismissible = config.dismissible ?? true;\r\n\r\n const cdkRef = cdk.open<R, D, unknown>(content, {\r\n data: config.data,\r\n role: config.role ?? 'dialog',\r\n ariaLabel: config.label ?? null,\r\n autoFocus: config.autoFocus ?? 'first-tabbable',\r\n restoreFocus: true,\r\n ariaModal: true,\r\n // Closing is handled here so the exit animation can play first.\r\n disableClose: true,\r\n hasBackdrop: true,\r\n backdropClass: 'hy-backdrop',\r\n panelClass: extra.panelClass,\r\n positionStrategy: extra.positionStrategy,\r\n width: extra.width,\r\n maxWidth: extra.maxWidth,\r\n height: extra.height,\r\n providers: (dialogRef) => {\r\n ref = new HyDialogRef<R>(dialogRef);\r\n return [\r\n { provide: HyDialogRef, useValue: ref },\r\n { provide: HY_DIALOG_DATA, useValue: config.data },\r\n ];\r\n },\r\n });\r\n\r\n const hyRef = ref ?? new HyDialogRef<R>(cdkRef);\r\n const container = hyRef.containerElement;\r\n if (container) {\r\n container.classList.add('hy-glass');\r\n container.dataset['material'] =\r\n fidelity.tier() === 'low' ? 'solid' : (config.material ?? 'frosted');\r\n // Dialogs and sheets are the largest glass on the page, so the thickest.\r\n container.dataset['thickness'] = 'thick';\r\n // With reduced motion the CSS cross-fade runs instead of the spring.\r\n if (extra.sheet && !motion.reduced()) {\r\n const driver = driveSheet(container, cdkRef.overlayRef.backdropElement, extra.sheet, {\r\n dismissible,\r\n close: () => hyRef.close(),\r\n cancelClose: () => hyRef.cancelClose(),\r\n });\r\n hyRef.exit = driver.exit;\r\n cdkRef.closed.subscribe(() => driver.destroy());\r\n }\r\n }\r\n if (dismissible) {\r\n cdkRef.backdropClick.subscribe(() => hyRef.close());\r\n cdkRef.keydownEvents\r\n .pipe(filter((e) => e.key === 'Escape' && !e.defaultPrevented))\r\n .subscribe((e) => {\r\n e.preventDefault();\r\n hyRef.close();\r\n });\r\n }\r\n return hyRef;\r\n}\r\n","import { Dialog } from '@angular/cdk/dialog';\r\nimport type { ComponentType } from '@angular/cdk/portal';\r\nimport { ChangeDetectionStrategy, Component, Injectable, TemplateRef, inject } from '@angular/core';\r\nimport { HyButton } from '@hyalo/angular/button';\r\n\r\nimport { HyFidelity, type HyTone } from '@hyalo/angular/core';\r\nimport { HyMotion } from '@hyalo/angular/motion';\r\n\r\nimport { HY_DIALOG_DATA, HyDialogRef } from './dialog-ref';\r\nimport { HY_DIALOG_PARTS } from './dialog-parts';\r\nimport { openSurface, type HySurfaceConfig } from './open-surface';\r\n\r\n/** Dialog width. `full` fills the screen on small viewports. */\r\nexport type HyDialogSize = 'sm' | 'md' | 'lg' | 'full';\r\n\r\n// Set inline because the CDK pane's own max-width sits outside our cascade layers.\r\nconst MAX_WIDTH: Record<HyDialogSize, string> = {\r\n sm: '26rem',\r\n md: '36rem',\r\n lg: '52rem',\r\n full: '72rem',\r\n};\r\n\r\n/** Options for {@link HyDialog.open}. */\r\nexport interface HyDialogConfig<D = unknown> extends HySurfaceConfig<D> {\r\n readonly size?: HyDialogSize;\r\n}\r\n\r\n/** Options for {@link HyDialog.confirm}. */\r\nexport interface HyConfirmOptions {\r\n readonly title: string;\r\n readonly message?: string;\r\n readonly confirmLabel?: string;\r\n readonly cancelLabel?: string;\r\n /** Use `danger` for destructive actions. */\r\n readonly tone?: HyTone;\r\n}\r\n\r\n@Component({\r\n selector: 'hy-confirm-dialog',\r\n imports: [HY_DIALOG_PARTS, HyButton],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './dialog.html',\r\n})\r\nclass HyConfirmDialog {\r\n protected readonly data = inject(HY_DIALOG_DATA) as HyConfirmOptions;\r\n}\r\n\r\n/**\r\n * Opens modal dialogs. Focus is trapped inside while open and returns to\r\n * the element that opened it. Escape and a backdrop click close it unless\r\n * `dismissible` is false.\r\n *\r\n * ```ts\r\n * const ref = this.dialog.open(EditAddress, { data: address, size: 'md' });\r\n * const saved = await ref.closed;\r\n *\r\n * if (await this.dialog.confirm({ title: 'Delete this draft?', tone: 'danger', confirmLabel: 'Delete' })) {\r\n * ...\r\n * }\r\n * ```\r\n *\r\n * In the content component, inject `HyDialogRef` to close and\r\n * `HY_DIALOG_DATA` to read the data. Lay it out with `hyDialogTitle`,\r\n * `hyDialogContent` and `hyDialogActions`.\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class HyDialog {\r\n private readonly cdk = inject(Dialog);\r\n private readonly motion = inject(HyMotion);\r\n private readonly fidelity = inject(HyFidelity);\r\n\r\n /** Opens a component or template as a dialog. */\r\n open<R = unknown, D = unknown>(\r\n content: ComponentType<unknown> | TemplateRef<unknown>,\r\n config: HyDialogConfig<D> = {},\r\n ): HyDialogRef<R> {\r\n const size = config.size ?? 'md';\r\n return openSurface<R, D>(this.cdk, this.motion, this.fidelity, content, config, {\r\n panelClass: ['hy-dialog-pane', `hy-dialog--${size}`],\r\n maxWidth: MAX_WIDTH[size],\r\n });\r\n }\r\n\r\n /** Asks a yes or no question. Resolves to true only when confirmed. */\r\n async confirm(options: HyConfirmOptions): Promise<boolean> {\r\n const ref = this.open<boolean, HyConfirmOptions>(HyConfirmDialog, {\r\n data: options,\r\n size: 'sm',\r\n role: 'alertdialog',\r\n });\r\n return (await ref.closed) === true;\r\n }\r\n}\r\n","<h2 hyDialogTitle>{{ data.title }}</h2>\r\n@if (data.message) {\r\n <p hyDialogContent>{{ data.message }}</p>\r\n}\r\n<div hyDialogActions>\r\n <button hyButton variant=\"ghost\" tone=\"neutral\" [hyDialogClose]=\"false\">\r\n {{ data.cancelLabel ?? 'Cancel' }}\r\n </button>\r\n <button hyButton [tone]=\"data.tone ?? 'primary'\" [hyDialogClose]=\"true\">\r\n {{ data.confirmLabel ?? 'Confirm' }}\r\n </button>\r\n</div>\r\n","import { Dialog } from '@angular/cdk/dialog';\r\nimport { createGlobalPositionStrategy } from '@angular/cdk/overlay';\r\nimport type { ComponentType } from '@angular/cdk/portal';\r\nimport { Injectable, Injector, TemplateRef, inject } from '@angular/core';\r\nimport { HyFidelity } from '@hyalo/angular/core';\r\nimport { HyMotion } from '@hyalo/angular/motion';\r\nimport type { HyDialogRef } from './dialog-ref';\r\nimport { openSurface, type HySurfaceConfig } from './open-surface';\r\n\r\n/**\r\n * Which edge the drawer slides from. `start` and `end` follow the text\r\n * direction, so `end` is the right edge in LTR and the left edge in RTL.\r\n * `bottom` gives a sheet, handy on phones.\r\n */\r\nexport type HyDrawerSide = 'start' | 'end' | 'bottom';\r\n\r\n/** Options for {@link HyDrawer.open}. */\r\nexport interface HyDrawerConfig<D = unknown> extends HySurfaceConfig<D> {\r\n readonly side?: HyDrawerSide;\r\n /** Any CSS length. Width for side drawers, height for the bottom sheet. */\r\n readonly size?: string;\r\n}\r\n\r\n/**\r\n * Opens a modal drawer: navigation on phones, a cart, filters. It behaves\r\n * like a dialog (focus trap, Escape, backdrop, focus restore) and uses the\r\n * same content parts and `HyDialogRef`.\r\n *\r\n * It runs on a spring and follows the pointer: drag it toward its edge, or\r\n * flick it, to close it, and grab it again while it moves. A bottom sheet\r\n * shows a grabber. With reduced motion it cross-fades instead.\r\n *\r\n * ```ts\r\n * this.drawer.open(CartPanel, { side: 'end', label: 'Cart' });\r\n * ```\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class HyDrawer {\r\n private readonly cdk = inject(Dialog);\r\n private readonly motion = inject(HyMotion);\r\n private readonly fidelity = inject(HyFidelity);\r\n private readonly injector = inject(Injector);\r\n\r\n /** Opens a component or template in a drawer. */\r\n open<R = unknown, D = unknown>(\r\n content: ComponentType<unknown> | TemplateRef<unknown>,\r\n config: HyDrawerConfig<D> = {},\r\n ): HyDialogRef<R> {\r\n const side = config.side ?? 'end';\r\n const position = createGlobalPositionStrategy(this.injector);\r\n if (side === 'bottom') position.bottom('0').centerHorizontally();\r\n else if (side === 'start') position.start('0').top('0');\r\n else position.end('0').top('0');\r\n\r\n return openSurface<R, D>(this.cdk, this.motion, this.fidelity, content, config, {\r\n panelClass: ['hy-drawer-pane', `hy-drawer--${side}`],\r\n positionStrategy: position,\r\n width: side === 'bottom' ? '100%' : (config.size ?? 'min(24rem, 100vw - 2.5rem)'),\r\n height: side === 'bottom' ? (config.size ?? 'auto') : '100%',\r\n sheet: side,\r\n });\r\n }\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, input } from "@angular/core";
3
+ var HyDivider = class HyDivider {
4
+ orientation = input("horizontal", ...ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []);
5
+ static ɵfac = i0.ɵɵngDeclareFactory({
6
+ minVersion: "12.0.0",
7
+ version: "22.2.3",
8
+ ngImport: i0,
9
+ type: HyDivider,
10
+ deps: [],
11
+ target: i0.ɵɵFactoryTarget.Component
12
+ });
13
+ static ɵcmp = i0.ɵɵngDeclareComponent({
14
+ minVersion: "17.1.0",
15
+ version: "22.2.3",
16
+ type: HyDivider,
17
+ isStandalone: true,
18
+ selector: "hy-divider",
19
+ inputs: { orientation: {
20
+ classPropertyName: "orientation",
21
+ publicName: "orientation",
22
+ isSignal: true,
23
+ isRequired: false,
24
+ transformFunction: null
25
+ } },
26
+ host: {
27
+ attributes: { "role": "separator" },
28
+ properties: { "attr.aria-orientation": "orientation()" }
29
+ },
30
+ ngImport: i0,
31
+ template: "",
32
+ isInline: true,
33
+ styles: [":host{display:block;border-block-start:1px solid var(--hy-line);margin-block:var(--hy-space-6)}:host([aria-orientation=\"vertical\"]){display:inline-block;align-self:stretch;border-block-start:0;border-inline-start:1px solid var(--hy-line);margin-block:0;margin-inline:var(--hy-space-3)}\n"],
34
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
35
+ });
36
+ };
37
+ i0.ɵɵngDeclareClassMetadata({
38
+ minVersion: "12.0.0",
39
+ version: "22.2.3",
40
+ ngImport: i0,
41
+ type: HyDivider,
42
+ decorators: [{
43
+ type: Component,
44
+ args: [{
45
+ selector: "hy-divider",
46
+ changeDetection: ChangeDetectionStrategy.OnPush,
47
+ host: {
48
+ role: "separator",
49
+ "[attr.aria-orientation]": "orientation()"
50
+ },
51
+ template: "",
52
+ styles: [":host{display:block;border-block-start:1px solid var(--hy-line);margin-block:var(--hy-space-6)}:host([aria-orientation=\"vertical\"]){display:inline-block;align-self:stretch;border-block-start:0;border-inline-start:1px solid var(--hy-line);margin-block:0;margin-inline:var(--hy-space-3)}\n"]
53
+ }]
54
+ }],
55
+ propDecorators: { orientation: [{
56
+ type: i0.Input,
57
+ args: [{
58
+ isSignal: true,
59
+ alias: "orientation",
60
+ required: false
61
+ }]
62
+ }] }
63
+ });
64
+ export { HyDivider };
65
+
66
+ //# sourceMappingURL=hyalo-angular-divider.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyalo-angular-divider.mjs","names":[],"sources":["../../../projects/hyalo/divider/divider.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\n@Component({\r\n selector: 'hy-divider',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { role: 'separator', '[attr.aria-orientation]': 'orientation()' },\r\n template: '',\r\n styleUrl: './divider.css',\r\n})\r\nexport class HyDivider {\r\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\r\n}\r\n"],"mappings":";;AAQA,IAAa,YAAb,MAAa,UAAS;CACX,cAAc,MAAiC,cAAa,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAD1D,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAS,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAT,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAS,cAAA;EAAA,UAAA;EAAA,QAAA,EAAA,aAAA;GAAA,mBAAA;GAAA,YAAA;GAAA,UAAA;GAAA,YAAA;GAAA,mBAAA;EAAA,EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,QAAA,YAAA;GAAA,YAAA,EAAA,yBAAA,gBAAA;EAAA;EAAA,UAAA;EAAA,UAHV;EAAE,UAAA;EAAA,QAAA,CAAA,mSAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAGD,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAS,YAAA,CAAA;EAPrB,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAY,iBACL,wBAAwB;GAAM,MACzC;IAAE,MAAM;IAAa,2BAA2B;GAAe;GAAE,UAC7D;GAAE,QAAA,CAAA,mSAAA;EAAA,CAAA"}
@@ -0,0 +1,123 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, input } from "@angular/core";
3
+ import { HyIcon } from "@hyalo/angular/icon";
4
+ var HyEmptyState = class HyEmptyState {
5
+ heading = input.required(...ngDevMode ? [{ debugName: "heading" }] : /* istanbul ignore next */ []);
6
+ headingLevel = input(2, ...ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []);
7
+ description = input("", ...ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []);
8
+ icon = input(...ngDevMode ? [void 0, { debugName: "icon" }] : /* istanbul ignore next */ []);
9
+ static ɵfac = i0.ɵɵngDeclareFactory({
10
+ minVersion: "12.0.0",
11
+ version: "22.2.3",
12
+ ngImport: i0,
13
+ type: HyEmptyState,
14
+ deps: [],
15
+ target: i0.ɵɵFactoryTarget.Component
16
+ });
17
+ static ɵcmp = i0.ɵɵngDeclareComponent({
18
+ minVersion: "17.0.0",
19
+ version: "22.2.3",
20
+ type: HyEmptyState,
21
+ isStandalone: true,
22
+ selector: "hy-empty-state",
23
+ inputs: {
24
+ heading: {
25
+ classPropertyName: "heading",
26
+ publicName: "heading",
27
+ isSignal: true,
28
+ isRequired: true,
29
+ transformFunction: null
30
+ },
31
+ headingLevel: {
32
+ classPropertyName: "headingLevel",
33
+ publicName: "headingLevel",
34
+ isSignal: true,
35
+ isRequired: false,
36
+ transformFunction: null
37
+ },
38
+ description: {
39
+ classPropertyName: "description",
40
+ publicName: "description",
41
+ isSignal: true,
42
+ isRequired: false,
43
+ transformFunction: null
44
+ },
45
+ icon: {
46
+ classPropertyName: "icon",
47
+ publicName: "icon",
48
+ isSignal: true,
49
+ isRequired: false,
50
+ transformFunction: null
51
+ }
52
+ },
53
+ ngImport: i0,
54
+ template: "@if (icon()) {\r\n <div class=\"symbol\"><hy-icon [name]=\"icon()!\" /></div>\r\n}\r\n@switch (headingLevel()) {\r\n @case (3) {\r\n <h3>{{ heading() }}</h3>\r\n }\r\n @case (4) {\r\n <h4>{{ heading() }}</h4>\r\n }\r\n @case (5) {\r\n <h5>{{ heading() }}</h5>\r\n }\r\n @case (6) {\r\n <h6>{{ heading() }}</h6>\r\n }\r\n @default {\r\n <h2>{{ heading() }}</h2>\r\n }\r\n}\r\n@if (description()) {\r\n <p>{{ description() }}</p>\r\n}\r\n<div class=\"actions\"><ng-content /></div>\r\n",
55
+ styles: [":host{display:grid;justify-items:center;text-align:center;padding:clamp(1.5rem,5vw,3rem);gap:.75rem;color:var(--hy-ink)}:is(h2,h3,h4,h5,h6),p{margin:0}:is(h2,h3,h4,h5,h6){font-size:var(--hy-step-2)}p{color:var(--hy-ink-2);max-inline-size:42ch}.symbol{display:grid;place-items:center;inline-size:3rem;block-size:3rem;background:var(--hy-primary-wash);color:var(--hy-primary);border-radius:var(--hy-radius-m)}.actions{display:flex;flex-wrap:wrap;justify-content:center;gap:.5rem;margin-block-start:.5rem}\n"],
56
+ dependencies: [{
57
+ kind: "component",
58
+ type: HyIcon,
59
+ selector: "hy-icon",
60
+ inputs: [
61
+ "name",
62
+ "icon",
63
+ "label",
64
+ "size",
65
+ "strokeWidth"
66
+ ]
67
+ }],
68
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
69
+ });
70
+ };
71
+ i0.ɵɵngDeclareClassMetadata({
72
+ minVersion: "12.0.0",
73
+ version: "22.2.3",
74
+ ngImport: i0,
75
+ type: HyEmptyState,
76
+ decorators: [{
77
+ type: Component,
78
+ args: [{
79
+ selector: "hy-empty-state",
80
+ imports: [HyIcon],
81
+ changeDetection: ChangeDetectionStrategy.OnPush,
82
+ template: "@if (icon()) {\r\n <div class=\"symbol\"><hy-icon [name]=\"icon()!\" /></div>\r\n}\r\n@switch (headingLevel()) {\r\n @case (3) {\r\n <h3>{{ heading() }}</h3>\r\n }\r\n @case (4) {\r\n <h4>{{ heading() }}</h4>\r\n }\r\n @case (5) {\r\n <h5>{{ heading() }}</h5>\r\n }\r\n @case (6) {\r\n <h6>{{ heading() }}</h6>\r\n }\r\n @default {\r\n <h2>{{ heading() }}</h2>\r\n }\r\n}\r\n@if (description()) {\r\n <p>{{ description() }}</p>\r\n}\r\n<div class=\"actions\"><ng-content /></div>\r\n",
83
+ styles: [":host{display:grid;justify-items:center;text-align:center;padding:clamp(1.5rem,5vw,3rem);gap:.75rem;color:var(--hy-ink)}:is(h2,h3,h4,h5,h6),p{margin:0}:is(h2,h3,h4,h5,h6){font-size:var(--hy-step-2)}p{color:var(--hy-ink-2);max-inline-size:42ch}.symbol{display:grid;place-items:center;inline-size:3rem;block-size:3rem;background:var(--hy-primary-wash);color:var(--hy-primary);border-radius:var(--hy-radius-m)}.actions{display:flex;flex-wrap:wrap;justify-content:center;gap:.5rem;margin-block-start:.5rem}\n"]
84
+ }]
85
+ }],
86
+ propDecorators: {
87
+ heading: [{
88
+ type: i0.Input,
89
+ args: [{
90
+ isSignal: true,
91
+ alias: "heading",
92
+ required: true
93
+ }]
94
+ }],
95
+ headingLevel: [{
96
+ type: i0.Input,
97
+ args: [{
98
+ isSignal: true,
99
+ alias: "headingLevel",
100
+ required: false
101
+ }]
102
+ }],
103
+ description: [{
104
+ type: i0.Input,
105
+ args: [{
106
+ isSignal: true,
107
+ alias: "description",
108
+ required: false
109
+ }]
110
+ }],
111
+ icon: [{
112
+ type: i0.Input,
113
+ args: [{
114
+ isSignal: true,
115
+ alias: "icon",
116
+ required: false
117
+ }]
118
+ }]
119
+ }
120
+ });
121
+ export { HyEmptyState };
122
+
123
+ //# sourceMappingURL=hyalo-angular-empty-state.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyalo-angular-empty-state.mjs","names":[],"sources":["../../../projects/hyalo/empty-state/empty-state.ts","../../../projects/hyalo/empty-state/empty-state.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, input } from '@angular/core';\r\nimport { HyIcon } from '@hyalo/angular/icon';\r\n@Component({\r\n selector: 'hy-empty-state',\r\n imports: [HyIcon],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './empty-state.html',\r\n styleUrl: './empty-state.css',\r\n})\r\nexport class HyEmptyState {\r\n readonly heading = input.required<string>();\r\n readonly headingLevel = input<2 | 3 | 4 | 5 | 6>(2);\r\n readonly description = input('');\r\n readonly icon = input<string>();\r\n}\r\n","@if (icon()) {\r\n <div class=\"symbol\"><hy-icon [name]=\"icon()!\" /></div>\r\n}\r\n@switch (headingLevel()) {\r\n @case (3) {\r\n <h3>{{ heading() }}</h3>\r\n }\r\n @case (4) {\r\n <h4>{{ heading() }}</h4>\r\n }\r\n @case (5) {\r\n <h5>{{ heading() }}</h5>\r\n }\r\n @case (6) {\r\n <h6>{{ heading() }}</h6>\r\n }\r\n @default {\r\n <h2>{{ heading() }}</h2>\r\n }\r\n}\r\n@if (description()) {\r\n <p>{{ description() }}</p>\r\n}\r\n<div class=\"actions\"><ng-content /></div>\r\n"],"mappings":";;;AASA,IAAa,eAAb,MAAa,aAAY;CACd,UAAU,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAClC,eAAe,MAAyB,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAC1C,cAAc,MAAM,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CACvB,OAAO,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAJpB,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,QAAA;GAAA,SAAA;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,aAAA;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,UAAA;EAAA,UCTzB;EAwBA,QAAA,CAAA,0fAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MDpBY;GAAM,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAKL,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAY,YAAA,CAAA;EAPxB,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAgB,SACjB,CAAC,MAAM;GAAC,iBACA,wBAAwB;GAAM,UAAA;GAAA,QAAA,CAAA,0fAAA;EAAA,CAAA"}
@@ -1,6 +1,7 @@
1
1
  import * as i0 from "@angular/core";
2
- import { ChangeDetectionStrategy, Component, Directive, HostAttributeToken, InjectionToken, booleanAttribute, computed, forwardRef, inject, input, signal } from "@angular/core";
3
- import { injectId } from "@hyalo/angular";
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, HostAttributeToken, InjectionToken, booleanAttribute, computed, forwardRef, inject, input, signal } from "@angular/core";
3
+ import { injectId } from "@hyalo/angular/core";
4
+ import { NgControl, Validators } from "@angular/forms";
4
5
  import { FORM_FIELD } from "@angular/forms/signals";
5
6
  const HY_FIELD = new InjectionToken("HY_FIELD");
6
7
  var HyInput = class HyInput {
@@ -9,22 +10,53 @@ var HyInput = class HyInput {
9
10
  self: true,
10
11
  optional: true
11
12
  });
13
+ ngControl = this.formField ? null : inject(NgControl, {
14
+ self: true,
15
+ optional: true
16
+ });
17
+ destroy = inject(DestroyRef);
18
+ revision = signal(0, ...ngDevMode ? [{ debugName: "revision" }] : /* istanbul ignore next */ []);
19
+ control;
20
+ subscription;
21
+ constructor() {
22
+ this.field?.register(this);
23
+ this.destroy.onDestroy(() => this.subscription?.unsubscribe());
24
+ }
25
+ ngDoCheck() {
26
+ const control = this.ngControl?.control;
27
+ if (control === this.control) return;
28
+ this.subscription?.unsubscribe();
29
+ this.control = control;
30
+ this.subscription = control?.events.subscribe(() => this.revision.update((value) => value + 1));
31
+ this.revision.update((value) => value + 1);
32
+ }
12
33
  labelable = true;
13
34
  id = signal(inject(new HostAttributeToken("id"), { optional: true }) ?? injectId("input")).asReadonly();
14
35
  invalid = computed(() => {
15
- const state = this.formField?.state();
16
- return !!state && state.invalid() && state.touched();
36
+ this.revision();
37
+ const state = this.formField?.state(), control = this.ngControl?.control;
38
+ return state ? state.invalid() && state.touched() : !!control?.invalid && control.touched;
17
39
  }, ...ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []);
18
40
  errorMessage = computed(() => {
41
+ this.revision();
42
+ const control = this.ngControl?.control;
43
+ if (!this.formField && control?.errors) {
44
+ const first = Object.keys(control.errors)[0];
45
+ const detail = first ? control.errors[first] : void 0;
46
+ return typeof detail === "object" && detail !== null && "message" in detail && typeof detail.message === "string" ? detail.message : first;
47
+ }
19
48
  const first = (this.formField?.state().errors() ?? [])[0];
20
49
  return first ? first.message ?? first.kind : void 0;
21
50
  }, ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
22
51
  showsError = computed(() => this.field ? this.field.errorShown() : this.invalid(), ...ngDevMode ? [{ debugName: "showsError" }] : /* istanbul ignore next */ []);
23
- required = computed(() => this.formField?.state().required() ?? false, ...ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []);
24
- disabled = computed(() => this.formField?.state().disabled() ?? false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
25
- constructor() {
26
- this.field?.register(this);
27
- }
52
+ required = computed(() => {
53
+ this.revision();
54
+ return this.formField?.state().required() ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false;
55
+ }, ...ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []);
56
+ disabled = computed(() => {
57
+ this.revision();
58
+ return this.formField?.state().disabled() ?? this.ngControl?.control?.disabled ?? false;
59
+ }, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
28
60
  static ɵfac = i0.ɵɵngDeclareFactory({
29
61
  minVersion: "12.0.0",
30
62
  version: "22.2.3",
@@ -1 +1 @@
1
- {"version":3,"file":"hyalo-angular-field.mjs","names":[],"sources":["../../../projects/hyalo/field/field-control.ts","../../../projects/hyalo/field/input.ts","../../../projects/hyalo/field/field.ts","../../../projects/hyalo/field/field.html"],"sourcesContent":["import { InjectionToken, type Signal } from '@angular/core';\r\n\r\n/**\r\n * What a control tells the field around it. Implemented by `hyInput` and\r\n * `hy-select`. Custom controls can implement it too, so `hy-field` can\r\n * label them and show their errors.\r\n */\r\nexport interface HyFieldControl {\r\n /** Id of the focusable element. */\r\n readonly id: Signal<string>;\r\n /** True when the field should show as invalid. */\r\n readonly invalid: Signal<boolean>;\r\n /** First error message to show, if any. */\r\n readonly errorMessage: Signal<string | undefined>;\r\n readonly required: Signal<boolean>;\r\n readonly disabled: Signal<boolean>;\r\n /**\r\n * True when the control is a native labelable element (input, textarea,\r\n * select, button). Those get `<label for>`. Others rely on\r\n * `aria-labelledby`.\r\n */\r\n readonly labelable: boolean;\r\n}\r\n\r\n/** The field a control sits in. */\r\nexport interface HyFieldContext {\r\n readonly labelId: string;\r\n readonly hintId: string;\r\n readonly errorId: string;\r\n /** True while the field displays an error. */\r\n readonly errorShown: Signal<boolean>;\r\n /** Space-separated ids for `aria-describedby`. */\r\n readonly describedBy: Signal<string | null>;\r\n register(control: HyFieldControl): void;\r\n}\r\n\r\n/** Provided by `hy-field` to the control inside it. */\r\nexport const HY_FIELD = new InjectionToken<HyFieldContext>('HY_FIELD');\r\n","import { Directive, HostAttributeToken, computed, inject, signal } from '@angular/core';\r\nimport { FORM_FIELD } from '@angular/forms/signals';\r\nimport { injectId } from '@hyalo/angular';\r\n\r\nimport { HY_FIELD, type HyFieldControl } from './field-control';\r\n\r\n/**\r\n * Marks a native `<input>` or `<textarea>` as the control of a `hy-field`.\r\n * It wires the label, hint and error ids, and reads validity from Signal\r\n * Forms when `[formField]` is on the same element.\r\n *\r\n * The element stays native, so Signal Forms, `ngModel`, autofill and\r\n * mobile keyboards all work as usual.\r\n */\r\n@Directive({\r\n selector: 'input[hyInput], textarea[hyInput]',\r\n host: {\r\n class: 'hy-input',\r\n '[id]': 'id()',\r\n '[attr.aria-describedby]': 'field?.describedBy() ?? null',\r\n '[attr.aria-invalid]': 'showsError() || null',\r\n },\r\n})\r\nexport class HyInput implements HyFieldControl {\r\n protected readonly field = inject(HY_FIELD, { optional: true });\r\n // The token, not the FormField class, so apps without forms do not bundle them.\r\n private readonly formField = inject(FORM_FIELD, { self: true, optional: true });\r\n\r\n readonly labelable = true;\r\n /** The element's own static `id` attribute, or a generated one. */\r\n readonly id = signal(\r\n inject(new HostAttributeToken('id'), { optional: true }) ?? injectId('input'),\r\n ).asReadonly();\r\n\r\n readonly invalid = computed(() => {\r\n const state = this.formField?.state();\r\n return !!state && state.invalid() && state.touched();\r\n });\r\n\r\n readonly errorMessage = computed(() => {\r\n const errors = this.formField?.state().errors() ?? [];\r\n const first = errors[0];\r\n return first ? (first.message ?? first.kind) : undefined;\r\n });\r\n\r\n protected readonly showsError = computed(() =>\r\n this.field ? this.field.errorShown() : this.invalid(),\r\n );\r\n\r\n readonly required = computed(() => this.formField?.state().required() ?? false);\r\n readonly disabled = computed(() => this.formField?.state().disabled() ?? false);\r\n\r\n constructor() {\r\n this.field?.register(this);\r\n }\r\n}\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n Directive,\r\n booleanAttribute,\r\n computed,\r\n forwardRef,\r\n input,\r\n signal,\r\n} from '@angular/core';\r\nimport { type HySize, injectId } from '@hyalo/angular';\r\n\r\nimport { HY_FIELD, type HyFieldContext, type HyFieldControl } from './field-control';\r\nimport { HyInput } from './input';\r\n\r\n/** Content before the control inside the field box, such as an icon. */\r\n@Directive({ selector: '[hyPrefix]', host: { class: 'hy-field__prefix' } })\r\nexport class HyPrefix {}\r\n\r\n/** Content after the control inside the field box, such as a unit or a button. */\r\n@Directive({ selector: '[hySuffix]', host: { class: 'hy-field__suffix' } })\r\nexport class HySuffix {}\r\n\r\n/**\r\n * Label, hint and error around one form control.\r\n *\r\n * ```html\r\n * <hy-field label=\"Email\" hint=\"Only used for the receipt\">\r\n * <hy-icon hyPrefix name=\"mail\" />\r\n * <input hyInput type=\"email\" [formField]=\"form.email\" />\r\n * </hy-field>\r\n * ```\r\n *\r\n * With Signal Forms the error comes from the field state and shows once the\r\n * field is touched. An explicit `error` input always wins, which is how\r\n * server-side errors are shown.\r\n */\r\n@Component({\r\n selector: 'hy-field',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n providers: [{ provide: HY_FIELD, useExisting: forwardRef(() => HyField) }],\r\n host: {\r\n class: 'hy-field',\r\n '[attr.data-size]': 'size()',\r\n '[attr.data-invalid]': 'errorShown() || null',\r\n '[attr.data-disabled]': 'control()?.disabled() || null',\r\n },\r\n templateUrl: './field.html',\r\n styleUrl: './field.css',\r\n})\r\nexport class HyField implements HyFieldContext {\r\n readonly labelId = injectId('field-label');\r\n readonly hintId = injectId('field-hint');\r\n readonly errorId = injectId('field-error');\r\n\r\n /** Visible label. Always set one, placeholders are not labels. */\r\n readonly label = input<string>();\r\n /** Help text under the control. Hidden while an error shows. */\r\n readonly hint = input<string>();\r\n /** Error text. Overrides errors from the form. */\r\n readonly error = input<string>();\r\n /** Show errors before the field is touched, for example after submit. */\r\n readonly forceError = input(false, { transform: booleanAttribute });\r\n /** Height of the field box. */\r\n readonly size = input<HySize>('md');\r\n\r\n protected readonly control = signal<HyFieldControl | undefined>(undefined);\r\n\r\n protected readonly labelFor = computed(() => {\r\n const c = this.control();\r\n return c?.labelable ? c.id() : null;\r\n });\r\n\r\n protected readonly errorText = computed(() => {\r\n if (this.error()) return this.error();\r\n const c = this.control();\r\n return c && (c.invalid() || this.forceError()) ? c.errorMessage() : undefined;\r\n });\r\n\r\n readonly errorShown = computed(() => !!this.errorText());\r\n\r\n readonly describedBy = computed(() => {\r\n const ids = [];\r\n if (this.hint() && !this.errorText()) ids.push(this.hintId);\r\n if (this.errorText()) ids.push(this.errorId);\r\n return ids.length ? ids.join(' ') : null;\r\n });\r\n\r\n register(control: HyFieldControl): void {\r\n this.control.set(control);\r\n }\r\n}\r\n\r\n/** Everything needed to build a text field. */\r\nexport const HY_TEXT_FIELD = [HyField, HyInput, HyPrefix, HySuffix] as const;\r\n","@if (label()) {\r\n <label class=\"hy-field__label\" [id]=\"labelId\" [attr.for]=\"labelFor()\">\r\n {{ label() }}\r\n @if (control()?.required()) {\r\n <span class=\"hy-field__required\" aria-hidden=\"true\">*</span>\r\n }\r\n </label>\r\n}\r\n<div class=\"hy-field__box\">\r\n <ng-content select=\"[hyPrefix]\" />\r\n <ng-content />\r\n <ng-content select=\"[hySuffix]\" />\r\n</div>\r\n@if (hint() && !errorText()) {\r\n <p class=\"hy-field__hint\" [id]=\"hintId\">{{ hint() }}</p>\r\n}\r\n<p class=\"hy-field__error\" [id]=\"errorId\" aria-live=\"polite\">{{ errorText() }}</p>\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"hyalo-angular-field.mjs","names":[],"sources":["../../../projects/hyalo/field/field-control.ts","../../../projects/hyalo/field/input.ts","../../../projects/hyalo/field/field.ts","../../../projects/hyalo/field/field.html"],"sourcesContent":["import { InjectionToken, type Signal } from '@angular/core';\r\n\r\n/**\r\n * What a control tells the field around it. Implemented by `hyInput` and\r\n * `hy-select`. Custom controls can implement it too, so `hy-field` can\r\n * label them and show their errors.\r\n */\r\nexport interface HyFieldControl {\r\n /** Id of the focusable element. */\r\n readonly id: Signal<string>;\r\n /** True when the field should show as invalid. */\r\n readonly invalid: Signal<boolean>;\r\n /** First error message to show, if any. */\r\n readonly errorMessage: Signal<string | undefined>;\r\n readonly required: Signal<boolean>;\r\n readonly disabled: Signal<boolean>;\r\n /**\r\n * True when the control is a native labelable element (input, textarea,\r\n * select, button). Those get `<label for>`. Others rely on\r\n * `aria-labelledby`.\r\n */\r\n readonly labelable: boolean;\r\n}\r\n\r\n/** The field a control sits in. */\r\nexport interface HyFieldContext {\r\n readonly labelId: string;\r\n readonly hintId: string;\r\n readonly errorId: string;\r\n /** True while the field displays an error. */\r\n readonly errorShown: Signal<boolean>;\r\n /** Space-separated ids for `aria-describedby`. */\r\n readonly describedBy: Signal<string | null>;\r\n register(control: HyFieldControl): void;\r\n}\r\n\r\n/** Provided by `hy-field` to the control inside it. */\r\nexport const HY_FIELD = new InjectionToken<HyFieldContext>('HY_FIELD');\r\n","import type { Subscription } from 'rxjs';\nimport { NgControl, Validators, type AbstractControl } from '@angular/forms';\nimport {\n Directive,\n HostAttributeToken,\n DestroyRef,\n DoCheck,\n computed,\n inject,\n signal,\n} from '@angular/core';\nimport { FORM_FIELD } from '@angular/forms/signals';\nimport { injectId } from '@hyalo/angular/core';\n\nimport { HY_FIELD, type HyFieldControl } from './field-control';\n\n/**\n * Marks a native `<input>` or `<textarea>` as the control of a `hy-field`.\n * It wires the label, hint and error ids, and reads validity from Signal\n * Forms when `[formField]` is on the same element.\n *\n * The element stays native, so Signal Forms, `ngModel`, autofill and\n * mobile keyboards all work as usual.\n */\n@Directive({\n selector: 'input[hyInput], textarea[hyInput]',\n host: {\n class: 'hy-input',\n '[id]': 'id()',\n '[attr.aria-describedby]': 'field?.describedBy() ?? null',\n '[attr.aria-invalid]': 'showsError() || null',\n },\n})\nexport class HyInput implements HyFieldControl, DoCheck {\n protected readonly field = inject(HY_FIELD, { optional: true });\n // The token, not the FormField class, so apps without forms do not bundle them.\n private readonly formField = inject(FORM_FIELD, { self: true, optional: true });\n\n // Signal Forms exposes a lightweight NgControl bridge, not an AbstractControl.\n // Its state is already reactive through FORM_FIELD, so no event subscription is needed.\n private readonly ngControl = this.formField\n ? null\n : inject(NgControl, { self: true, optional: true });\n private readonly destroy = inject(DestroyRef);\n private readonly revision = signal(0);\n private control: AbstractControl | null | undefined;\n private subscription?: Subscription;\n constructor() {\n this.field?.register(this);\n this.destroy.onDestroy(() => this.subscription?.unsubscribe());\n }\n ngDoCheck(): void {\n const control = this.ngControl?.control;\n if (control === this.control) return;\n this.subscription?.unsubscribe();\n this.control = control;\n this.subscription = control?.events.subscribe(() => this.revision.update((value) => value + 1));\n this.revision.update((value) => value + 1);\n }\n readonly labelable = true;\n /** The element's own static `id` attribute, or a generated one. */\n readonly id = signal(\n inject(new HostAttributeToken('id'), { optional: true }) ?? injectId('input'),\n ).asReadonly();\n\n readonly invalid = computed(() => {\n this.revision();\n const state = this.formField?.state(),\n control = this.ngControl?.control;\n return state ? state.invalid() && state.touched() : !!control?.invalid && control.touched;\n });\n\n readonly errorMessage = computed(() => {\n this.revision();\n const control = this.ngControl?.control;\n if (!this.formField && control?.errors) {\n const first = Object.keys(control.errors)[0];\n const detail: unknown = first ? control.errors[first] : undefined;\n return typeof detail === 'object' &&\n detail !== null &&\n 'message' in detail &&\n typeof detail.message === 'string'\n ? detail.message\n : first;\n }\n const errors = this.formField?.state().errors() ?? [];\n const first = errors[0];\n return first ? (first.message ?? first.kind) : undefined;\n });\n\n protected readonly showsError = computed(() =>\n this.field ? this.field.errorShown() : this.invalid(),\n );\n\n readonly required = computed(() => {\n this.revision();\n return (\n this.formField?.state().required() ??\n this.ngControl?.control?.hasValidator(Validators.required) ??\n false\n );\n });\n readonly disabled = computed(() => {\n this.revision();\n return this.formField?.state().disabled() ?? this.ngControl?.control?.disabled ?? false;\n });\n}\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n Directive,\r\n booleanAttribute,\r\n computed,\r\n forwardRef,\r\n input,\r\n signal,\r\n} from '@angular/core';\r\nimport { type HySize, injectId } from '@hyalo/angular/core';\r\n\r\nimport { HY_FIELD, type HyFieldContext, type HyFieldControl } from './field-control';\r\nimport { HyInput } from './input';\r\n\r\n/** Content before the control inside the field box, such as an icon. */\r\n@Directive({ selector: '[hyPrefix]', host: { class: 'hy-field__prefix' } })\r\nexport class HyPrefix {}\r\n\r\n/** Content after the control inside the field box, such as a unit or a button. */\r\n@Directive({ selector: '[hySuffix]', host: { class: 'hy-field__suffix' } })\r\nexport class HySuffix {}\r\n\r\n/**\r\n * Label, hint and error around one form control.\r\n *\r\n * ```html\r\n * <hy-field label=\"Email\" hint=\"Only used for the receipt\">\r\n * <hy-icon hyPrefix name=\"mail\" />\r\n * <input hyInput type=\"email\" [formField]=\"form.email\" />\r\n * </hy-field>\r\n * ```\r\n *\r\n * With Signal Forms the error comes from the field state and shows once the\r\n * field is touched. An explicit `error` input always wins, which is how\r\n * server-side errors are shown.\r\n */\r\n@Component({\r\n selector: 'hy-field',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n providers: [{ provide: HY_FIELD, useExisting: forwardRef(() => HyField) }],\r\n host: {\r\n class: 'hy-field',\r\n '[attr.data-size]': 'size()',\r\n '[attr.data-invalid]': 'errorShown() || null',\r\n '[attr.data-disabled]': 'control()?.disabled() || null',\r\n },\r\n templateUrl: './field.html',\r\n styleUrl: './field.css',\r\n})\r\nexport class HyField implements HyFieldContext {\r\n readonly labelId = injectId('field-label');\r\n readonly hintId = injectId('field-hint');\r\n readonly errorId = injectId('field-error');\r\n\r\n /** Visible label. Always set one, placeholders are not labels. */\r\n readonly label = input<string>();\r\n /** Help text under the control. Hidden while an error shows. */\r\n readonly hint = input<string>();\r\n /** Error text. Overrides errors from the form. */\r\n readonly error = input<string>();\r\n /** Show errors before the field is touched, for example after submit. */\r\n readonly forceError = input(false, { transform: booleanAttribute });\r\n /** Height of the field box. */\r\n readonly size = input<HySize>('md');\r\n\r\n protected readonly control = signal<HyFieldControl | undefined>(undefined);\r\n\r\n protected readonly labelFor = computed(() => {\r\n const c = this.control();\r\n return c?.labelable ? c.id() : null;\r\n });\r\n\r\n protected readonly errorText = computed(() => {\r\n if (this.error()) return this.error();\r\n const c = this.control();\r\n return c && (c.invalid() || this.forceError()) ? c.errorMessage() : undefined;\r\n });\r\n\r\n readonly errorShown = computed(() => !!this.errorText());\r\n\r\n readonly describedBy = computed(() => {\r\n const ids = [];\r\n if (this.hint() && !this.errorText()) ids.push(this.hintId);\r\n if (this.errorText()) ids.push(this.errorId);\r\n return ids.length ? ids.join(' ') : null;\r\n });\r\n\r\n register(control: HyFieldControl): void {\r\n this.control.set(control);\r\n }\r\n}\r\n\r\n/** Everything needed to build a text field. */\r\nexport const HY_TEXT_FIELD = [HyField, HyInput, HyPrefix, HySuffix] as const;\r\n","@if (label()) {\r\n <label class=\"hy-field__label\" [id]=\"labelId\" [attr.for]=\"labelFor()\">\r\n {{ label() }}\r\n @if (control()?.required()) {\r\n <span class=\"hy-field__required\" aria-hidden=\"true\">*</span>\r\n }\r\n </label>\r\n}\r\n<div class=\"hy-field__box\">\r\n <ng-content select=\"[hyPrefix]\" />\r\n <ng-content />\r\n <ng-content select=\"[hySuffix]\" />\r\n</div>\r\n@if (hint() && !errorText()) {\r\n <p class=\"hy-field__hint\" [id]=\"hintId\">{{ hint() }}</p>\r\n}\r\n<p class=\"hy-field__error\" [id]=\"errorId\" aria-live=\"polite\">{{ errorText() }}</p>\r\n"],"mappings":"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"}