@frame-kit/ui-ng 0.0.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 (220) hide show
  1. package/COMPONENTS.md +683 -0
  2. package/DEVELOPMENT_GUIDE.md +1102 -0
  3. package/LICENSE +21 -0
  4. package/README.md +69 -0
  5. package/THEMING.md +130 -0
  6. package/core/headline/README.md +121 -0
  7. package/core/icon/README.md +173 -0
  8. package/core/image/README.md +210 -0
  9. package/core/link/README.md +297 -0
  10. package/core/separator/README.md +145 -0
  11. package/core/text/README.md +240 -0
  12. package/directives/infinite-scroll/README.md +102 -0
  13. package/directives/spotlight/README.md +154 -0
  14. package/directives/tooltip/README.md +147 -0
  15. package/docs/endpoint-link/README.md +142 -0
  16. package/docs/method-badge/README.md +154 -0
  17. package/fesm2022/frame-kit-ui-ng-core-headline.mjs +122 -0
  18. package/fesm2022/frame-kit-ui-ng-core-headline.mjs.map +1 -0
  19. package/fesm2022/frame-kit-ui-ng-core-icon.mjs +189 -0
  20. package/fesm2022/frame-kit-ui-ng-core-icon.mjs.map +1 -0
  21. package/fesm2022/frame-kit-ui-ng-core-image.mjs +123 -0
  22. package/fesm2022/frame-kit-ui-ng-core-image.mjs.map +1 -0
  23. package/fesm2022/frame-kit-ui-ng-core-link.mjs +369 -0
  24. package/fesm2022/frame-kit-ui-ng-core-link.mjs.map +1 -0
  25. package/fesm2022/frame-kit-ui-ng-core-separator.mjs +59 -0
  26. package/fesm2022/frame-kit-ui-ng-core-separator.mjs.map +1 -0
  27. package/fesm2022/frame-kit-ui-ng-core-text.mjs +204 -0
  28. package/fesm2022/frame-kit-ui-ng-core-text.mjs.map +1 -0
  29. package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs +74 -0
  30. package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs.map +1 -0
  31. package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs +76 -0
  32. package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs.map +1 -0
  33. package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs +425 -0
  34. package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs.map +1 -0
  35. package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs +63 -0
  36. package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs.map +1 -0
  37. package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs +43 -0
  38. package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs.map +1 -0
  39. package/fesm2022/frame-kit-ui-ng-forms.mjs +3632 -0
  40. package/fesm2022/frame-kit-ui-ng-forms.mjs.map +1 -0
  41. package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs +239 -0
  42. package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs.map +1 -0
  43. package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs +132 -0
  44. package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs.map +1 -0
  45. package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs +133 -0
  46. package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs.map +1 -0
  47. package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs +60 -0
  48. package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs.map +1 -0
  49. package/fesm2022/frame-kit-ui-ng-services-toast.mjs +166 -0
  50. package/fesm2022/frame-kit-ui-ng-services-toast.mjs.map +1 -0
  51. package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs +214 -0
  52. package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs.map +1 -0
  53. package/fesm2022/frame-kit-ui-ng-ui-alert.mjs +82 -0
  54. package/fesm2022/frame-kit-ui-ng-ui-alert.mjs.map +1 -0
  55. package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs +76 -0
  56. package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs.map +1 -0
  57. package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs +81 -0
  58. package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs.map +1 -0
  59. package/fesm2022/frame-kit-ui-ng-ui-badge.mjs +81 -0
  60. package/fesm2022/frame-kit-ui-ng-ui-badge.mjs.map +1 -0
  61. package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs +68 -0
  62. package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs.map +1 -0
  63. package/fesm2022/frame-kit-ui-ng-ui-button.mjs +108 -0
  64. package/fesm2022/frame-kit-ui-ng-ui-button.mjs.map +1 -0
  65. package/fesm2022/frame-kit-ui-ng-ui-callout.mjs +58 -0
  66. package/fesm2022/frame-kit-ui-ng-ui-callout.mjs.map +1 -0
  67. package/fesm2022/frame-kit-ui-ng-ui-card.mjs +70 -0
  68. package/fesm2022/frame-kit-ui-ng-ui-card.mjs.map +1 -0
  69. package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs +113 -0
  70. package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs.map +1 -0
  71. package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs +1288 -0
  72. package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs.map +1 -0
  73. package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs +456 -0
  74. package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs.map +1 -0
  75. package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs +398 -0
  76. package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs.map +1 -0
  77. package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs +398 -0
  78. package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs.map +1 -0
  79. package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs +125 -0
  80. package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs.map +1 -0
  81. package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs +113 -0
  82. package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs.map +1 -0
  83. package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs +111 -0
  84. package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs.map +1 -0
  85. package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs +103 -0
  86. package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs.map +1 -0
  87. package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs +135 -0
  88. package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs.map +1 -0
  89. package/fesm2022/frame-kit-ui-ng-ui-loader.mjs +81 -0
  90. package/fesm2022/frame-kit-ui-ng-ui-loader.mjs.map +1 -0
  91. package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs +79 -0
  92. package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs.map +1 -0
  93. package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs +40 -0
  94. package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs.map +1 -0
  95. package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs +110 -0
  96. package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs.map +1 -0
  97. package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs +91 -0
  98. package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs.map +1 -0
  99. package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs +86 -0
  100. package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs.map +1 -0
  101. package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs +443 -0
  102. package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs.map +1 -0
  103. package/fesm2022/frame-kit-ui-ng-ui-note.mjs +56 -0
  104. package/fesm2022/frame-kit-ui-ng-ui-note.mjs.map +1 -0
  105. package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs +105 -0
  106. package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs.map +1 -0
  107. package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs +110 -0
  108. package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs.map +1 -0
  109. package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs +129 -0
  110. package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs.map +1 -0
  111. package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs +42 -0
  112. package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs.map +1 -0
  113. package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs +894 -0
  114. package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs.map +1 -0
  115. package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs +81 -0
  116. package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs.map +1 -0
  117. package/fesm2022/frame-kit-ui-ng-ui-toast.mjs +179 -0
  118. package/fesm2022/frame-kit-ui-ng-ui-toast.mjs.map +1 -0
  119. package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs +143 -0
  120. package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs.map +1 -0
  121. package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs +191 -0
  122. package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs.map +1 -0
  123. package/fesm2022/frame-kit-ui-ng.mjs +58 -0
  124. package/fesm2022/frame-kit-ui-ng.mjs.map +1 -0
  125. package/layouts/app-shell/README.md +357 -0
  126. package/layouts/content-split/README.md +180 -0
  127. package/package.json +253 -0
  128. package/services/overlay-orchestrator/README.md +184 -0
  129. package/services/spotlight/README.md +61 -0
  130. package/services/toast/README.md +118 -0
  131. package/types/frame-kit-ui-ng-core-headline.d.ts +38 -0
  132. package/types/frame-kit-ui-ng-core-icon.d.ts +74 -0
  133. package/types/frame-kit-ui-ng-core-image.d.ts +93 -0
  134. package/types/frame-kit-ui-ng-core-link.d.ts +251 -0
  135. package/types/frame-kit-ui-ng-core-separator.d.ts +28 -0
  136. package/types/frame-kit-ui-ng-core-text.d.ts +186 -0
  137. package/types/frame-kit-ui-ng-directives-infinite-scroll.d.ts +42 -0
  138. package/types/frame-kit-ui-ng-directives-spotlight.d.ts +51 -0
  139. package/types/frame-kit-ui-ng-directives-tooltip.d.ts +70 -0
  140. package/types/frame-kit-ui-ng-docs-endpoint-link.d.ts +43 -0
  141. package/types/frame-kit-ui-ng-docs-method-badge.d.ts +30 -0
  142. package/types/frame-kit-ui-ng-forms.d.ts +1674 -0
  143. package/types/frame-kit-ui-ng-layouts-app-shell.d.ts +75 -0
  144. package/types/frame-kit-ui-ng-layouts-content-split.d.ts +43 -0
  145. package/types/frame-kit-ui-ng-services-overlay-orchestrator.d.ts +96 -0
  146. package/types/frame-kit-ui-ng-services-spotlight.d.ts +32 -0
  147. package/types/frame-kit-ui-ng-services-toast.d.ts +100 -0
  148. package/types/frame-kit-ui-ng-ui-accordion.d.ts +86 -0
  149. package/types/frame-kit-ui-ng-ui-alert.d.ts +34 -0
  150. package/types/frame-kit-ui-ng-ui-avatar-stack.d.ts +38 -0
  151. package/types/frame-kit-ui-ng-ui-avatar.d.ts +36 -0
  152. package/types/frame-kit-ui-ng-ui-badge.d.ts +33 -0
  153. package/types/frame-kit-ui-ng-ui-breadcrumb.d.ts +45 -0
  154. package/types/frame-kit-ui-ng-ui-button.d.ts +48 -0
  155. package/types/frame-kit-ui-ng-ui-callout.d.ts +26 -0
  156. package/types/frame-kit-ui-ng-ui-card.d.ts +30 -0
  157. package/types/frame-kit-ui-ng-ui-copyable-field.d.ts +62 -0
  158. package/types/frame-kit-ui-ng-ui-data-table.d.ts +482 -0
  159. package/types/frame-kit-ui-ng-ui-dialog.d.ts +166 -0
  160. package/types/frame-kit-ui-ng-ui-drawer.d.ts +130 -0
  161. package/types/frame-kit-ui-ng-ui-dropdown-menu.d.ts +77 -0
  162. package/types/frame-kit-ui-ng-ui-editable-field.d.ts +65 -0
  163. package/types/frame-kit-ui-ng-ui-icon-badge.d.ts +45 -0
  164. package/types/frame-kit-ui-ng-ui-icon-list.d.ts +67 -0
  165. package/types/frame-kit-ui-ng-ui-inline-edit.d.ts +44 -0
  166. package/types/frame-kit-ui-ng-ui-list-editor.d.ts +56 -0
  167. package/types/frame-kit-ui-ng-ui-loader.d.ts +32 -0
  168. package/types/frame-kit-ui-ng-ui-menu-item.d.ts +27 -0
  169. package/types/frame-kit-ui-ng-ui-nav-brand.d.ts +25 -0
  170. package/types/frame-kit-ui-ng-ui-nav-group.d.ts +60 -0
  171. package/types/frame-kit-ui-ng-ui-nav-separator.d.ts +33 -0
  172. package/types/frame-kit-ui-ng-ui-node-tree-breadcrumb.d.ts +35 -0
  173. package/types/frame-kit-ui-ng-ui-node-tree.d.ts +135 -0
  174. package/types/frame-kit-ui-ng-ui-note.d.ts +22 -0
  175. package/types/frame-kit-ui-ng-ui-numbered-list.d.ts +52 -0
  176. package/types/frame-kit-ui-ng-ui-pagination.d.ts +49 -0
  177. package/types/frame-kit-ui-ng-ui-progress-bar.d.ts +50 -0
  178. package/types/frame-kit-ui-ng-ui-sidenav-link.d.ts +24 -0
  179. package/types/frame-kit-ui-ng-ui-tabs.d.ts +266 -0
  180. package/types/frame-kit-ui-ng-ui-timeline.d.ts +42 -0
  181. package/types/frame-kit-ui-ng-ui-toast.d.ts +56 -0
  182. package/types/frame-kit-ui-ng-ui-user-menu.d.ts +87 -0
  183. package/types/frame-kit-ui-ng-ui-wizard-dialog.d.ts +116 -0
  184. package/types/frame-kit-ui-ng.d.ts +53 -0
  185. package/ui/accordion/README.md +261 -0
  186. package/ui/alert/README.md +211 -0
  187. package/ui/avatar/README.md +167 -0
  188. package/ui/avatar-stack/README.md +164 -0
  189. package/ui/badge/README.md +162 -0
  190. package/ui/breadcrumb/README.md +240 -0
  191. package/ui/button/README.md +184 -0
  192. package/ui/callout/README.md +159 -0
  193. package/ui/card/README.md +174 -0
  194. package/ui/copyable-field/README.md +235 -0
  195. package/ui/data-table/README.md +408 -0
  196. package/ui/dialog/README.md +222 -0
  197. package/ui/drawer/README.md +274 -0
  198. package/ui/dropdown-menu/README.md +336 -0
  199. package/ui/editable-field/README.md +171 -0
  200. package/ui/icon-badge/README.md +131 -0
  201. package/ui/icon-list/README.md +205 -0
  202. package/ui/inline-edit/README.md +135 -0
  203. package/ui/list-editor/README.md +162 -0
  204. package/ui/loader/README.md +160 -0
  205. package/ui/menu-item/README.md +204 -0
  206. package/ui/nav-brand/README.md +111 -0
  207. package/ui/nav-group/README.md +145 -0
  208. package/ui/nav-separator/README.md +44 -0
  209. package/ui/node-tree/README.md +278 -0
  210. package/ui/node-tree-breadcrumb/README.md +164 -0
  211. package/ui/note/README.md +146 -0
  212. package/ui/numbered-list/README.md +187 -0
  213. package/ui/pagination/README.md +174 -0
  214. package/ui/progress-bar/README.md +223 -0
  215. package/ui/sidenav-link/README.md +214 -0
  216. package/ui/tabs/README.md +204 -0
  217. package/ui/timeline/README.md +285 -0
  218. package/ui/toast/README.md +243 -0
  219. package/ui/user-menu/README.md +260 -0
  220. package/ui/wizard-dialog/README.md +283 -0
@@ -0,0 +1,108 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Directive, input, contentChild, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { LoaderComponent } from '@frame-kit/ui-ng/ui/loader';
4
+
5
+ const FK_BUTTON_ICON_START = new InjectionToken('FK_BUTTON_ICON_START');
6
+ const FK_BUTTON_ICON_END = new InjectionToken('FK_BUTTON_ICON_END');
7
+ class FkButtonIconStartDirective {
8
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkButtonIconStartDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
9
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: FkButtonIconStartDirective, isStandalone: true, selector: "[fkButtonIconStart]", host: { attributes: { "aria-hidden": "true" } }, providers: [
10
+ { provide: FK_BUTTON_ICON_START, useExisting: FkButtonIconStartDirective },
11
+ ], ngImport: i0 });
12
+ }
13
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkButtonIconStartDirective, decorators: [{
14
+ type: Directive,
15
+ args: [{
16
+ selector: '[fkButtonIconStart]',
17
+ standalone: true,
18
+ providers: [
19
+ { provide: FK_BUTTON_ICON_START, useExisting: FkButtonIconStartDirective },
20
+ ],
21
+ host: {
22
+ 'aria-hidden': 'true',
23
+ },
24
+ }]
25
+ }] });
26
+ class FkButtonIconEndDirective {
27
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkButtonIconEndDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
28
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: FkButtonIconEndDirective, isStandalone: true, selector: "[fkButtonIconEnd]", host: { attributes: { "aria-hidden": "true" } }, providers: [
29
+ { provide: FK_BUTTON_ICON_END, useExisting: FkButtonIconEndDirective },
30
+ ], ngImport: i0 });
31
+ }
32
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FkButtonIconEndDirective, decorators: [{
33
+ type: Directive,
34
+ args: [{
35
+ selector: '[fkButtonIconEnd]',
36
+ standalone: true,
37
+ providers: [
38
+ { provide: FK_BUTTON_ICON_END, useExisting: FkButtonIconEndDirective },
39
+ ],
40
+ host: {
41
+ 'aria-hidden': 'true',
42
+ },
43
+ }]
44
+ }] });
45
+
46
+ class ButtonComponent {
47
+ // ===== BEHAVIOR =====
48
+ /** Visual style variant of the button (primary, secondary, ghost, etc.). */
49
+ variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
50
+ /** Size of the button, affecting padding and font size. */
51
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
52
+ /** When true, shows a spinner and disables interaction. */
53
+ loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
54
+ /** When true, prevents interaction and applies disabled styling. */
55
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
56
+ /** HTML type attribute forwarded to the inner `<button>` element. */
57
+ type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
58
+ /** When true, the button stretches to fill its container width. */
59
+ fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : /* istanbul ignore next */ []));
60
+ // ===== CONTENT CHILDREN =====
61
+ iconStartRef = contentChild(FK_BUTTON_ICON_START, ...(ngDevMode ? [{ debugName: "iconStartRef" }] : /* istanbul ignore next */ []));
62
+ iconEndRef = contentChild(FK_BUTTON_ICON_END, ...(ngDevMode ? [{ debugName: "iconEndRef" }] : /* istanbul ignore next */ []));
63
+ // ===== BASE PROPS =====
64
+ id = input(null, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
65
+ className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
66
+ ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
67
+ ariaDescribedBy = input(null, ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []));
68
+ // ===== COMPUTED =====
69
+ isDisabled = computed(() => this.disabled() || this.loading(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
70
+ classes = computed(() => {
71
+ return [
72
+ 'fk-button',
73
+ `fk-button--${this.variant()}`,
74
+ `fk-button--${this.size()}`,
75
+ this.isDisabled() ? 'fk-button--disabled' : '',
76
+ this.loading() ? 'fk-button--loading' : '',
77
+ this.fullWidth() ? 'fk-button--full-width' : '',
78
+ this.className(),
79
+ ]
80
+ .filter(Boolean)
81
+ .join(' ');
82
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
83
+ get hostClass() {
84
+ return this.classes();
85
+ }
86
+ get ariaDisabledAttr() {
87
+ return this.isDisabled() ? 'true' : null;
88
+ }
89
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
90
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ButtonComponent, isStandalone: true, selector: "fk-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "ariaDescribedBy", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "attr.aria-disabled": "this.ariaDisabledAttr" } }, queries: [{ propertyName: "iconStartRef", first: true, predicate: FK_BUTTON_ICON_START, descendants: true, isSignal: true }, { propertyName: "iconEndRef", first: true, predicate: FK_BUTTON_ICON_END, descendants: true, isSignal: true }], ngImport: i0, template: "<button\n class=\"fk-button__native\"\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n>\n @if (loading()) {\n <fk-loader\n className=\"fk-button__loader\"\n size=\"sm\"\n color=\"inherit\"\n ariaLabel=\"Loading\"\n ></fk-loader>\n }\n <span\n class=\"fk-button__content\"\n [class.fk-button__content--hidden]=\"loading()\"\n >\n <ng-content select=\"[fkButtonIconStart]\" />\n <ng-content />\n <ng-content select=\"[fkButtonIconEnd]\" />\n </span>\n</button>\n", styles: [":host{display:inline-block}:host.fk-button--full-width{display:block;width:100%}.fk-button__native{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--fk-button-icon-gap, .5rem);border:var(--fk-button-border-width, 1px) solid transparent;border-radius:var(--fk-button-border-radius, .5rem);font-weight:var(--fk-button-font-weight, var(--fk-typography-button-font-weight, 400));line-height:var(--fk-button-line-height, var(--fk-typography-button-line-height, 1.5));cursor:var(--fk-button-cursor, pointer);transition:var(--fk-button-transition, background-color .15s ease, border-color .15s ease, color .15s ease);text-decoration:none;white-space:nowrap;width:100%}.fk-button__native:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-button__content{display:inline-flex;align-items:center;gap:var(--fk-button-icon-gap, .5rem)}.fk-button__content--hidden{visibility:hidden}.fk-button__loader{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}:host.fk-button--sm .fk-button__native{padding:var(--fk-button-padding-sm, .375rem .75rem);font-size:var(--fk-button-font-size-sm, .875rem)}:host.fk-button--md .fk-button__native{padding:var(--fk-button-padding-md, .5rem 1rem);font-size:var(--fk-button-font-size-md, 1rem)}:host.fk-button--lg .fk-button__native{padding:var(--fk-button-padding-lg, .625rem 1.25rem);font-size:var(--fk-button-font-size-lg, 1.125rem)}:host.fk-button--primary .fk-button__native{background-color:var(--fk-button-primary-bg, var(--fk-color-primary, #0a84ff));color:var(--fk-button-primary-color, var(--fk-color-surface, #ffffff));border-color:var(--fk-button-primary-border-color, transparent)}:host.fk-button--primary:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-primary-bg-hover, var(--fk-color-primary-hover, #0670e0))}:host.fk-button--primary:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-primary-bg-active, var(--fk-color-primary-active, #055fc3))}:host.fk-button--secondary .fk-button__native{background-color:var(--fk-button-secondary-bg, transparent);color:var(--fk-button-secondary-color, var(--fk-color-primary, #0a84ff));border-color:var(--fk-button-secondary-border-color, var(--fk-color-border, #d9e2ee))}:host.fk-button--secondary:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-secondary-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}:host.fk-button--secondary:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-secondary-bg-active, var(--fk-color-border, #d9e2ee))}:host.fk-button--outline .fk-button__native{background-color:var(--fk-button-outline-bg, transparent);color:var(--fk-button-outline-color, var(--fk-color-primary, #0a84ff));border-color:var(--fk-button-outline-border-color, var(--fk-color-border, #d9e2ee))}:host.fk-button--outline:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-outline-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}:host.fk-button--outline:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-outline-bg-active, var(--fk-color-border, #d9e2ee))}:host.fk-button--danger .fk-button__native{background-color:var(--fk-button-danger-bg, var(--fk-color-danger, #e02424));color:var(--fk-button-danger-color, var(--fk-color-surface, #ffffff));border-color:var(--fk-button-danger-border-color, transparent)}:host.fk-button--danger:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-danger-bg-hover, #b91c1c)}:host.fk-button--danger:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-danger-bg-active, #991b1b)}:host.fk-button--disabled .fk-button__native{opacity:var(--fk-button-opacity-disabled, .6);cursor:var(--fk-button-cursor-disabled, not-allowed)}\n"], dependencies: [{ kind: "component", type: LoaderComponent, selector: "fk-loader", inputs: ["size", "color", "className", "id", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
91
+ }
92
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, decorators: [{
93
+ type: Component,
94
+ args: [{ selector: 'fk-button', standalone: true, imports: [LoaderComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n class=\"fk-button__native\"\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n>\n @if (loading()) {\n <fk-loader\n className=\"fk-button__loader\"\n size=\"sm\"\n color=\"inherit\"\n ariaLabel=\"Loading\"\n ></fk-loader>\n }\n <span\n class=\"fk-button__content\"\n [class.fk-button__content--hidden]=\"loading()\"\n >\n <ng-content select=\"[fkButtonIconStart]\" />\n <ng-content />\n <ng-content select=\"[fkButtonIconEnd]\" />\n </span>\n</button>\n", styles: [":host{display:inline-block}:host.fk-button--full-width{display:block;width:100%}.fk-button__native{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--fk-button-icon-gap, .5rem);border:var(--fk-button-border-width, 1px) solid transparent;border-radius:var(--fk-button-border-radius, .5rem);font-weight:var(--fk-button-font-weight, var(--fk-typography-button-font-weight, 400));line-height:var(--fk-button-line-height, var(--fk-typography-button-line-height, 1.5));cursor:var(--fk-button-cursor, pointer);transition:var(--fk-button-transition, background-color .15s ease, border-color .15s ease, color .15s ease);text-decoration:none;white-space:nowrap;width:100%}.fk-button__native:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-button__content{display:inline-flex;align-items:center;gap:var(--fk-button-icon-gap, .5rem)}.fk-button__content--hidden{visibility:hidden}.fk-button__loader{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}:host.fk-button--sm .fk-button__native{padding:var(--fk-button-padding-sm, .375rem .75rem);font-size:var(--fk-button-font-size-sm, .875rem)}:host.fk-button--md .fk-button__native{padding:var(--fk-button-padding-md, .5rem 1rem);font-size:var(--fk-button-font-size-md, 1rem)}:host.fk-button--lg .fk-button__native{padding:var(--fk-button-padding-lg, .625rem 1.25rem);font-size:var(--fk-button-font-size-lg, 1.125rem)}:host.fk-button--primary .fk-button__native{background-color:var(--fk-button-primary-bg, var(--fk-color-primary, #0a84ff));color:var(--fk-button-primary-color, var(--fk-color-surface, #ffffff));border-color:var(--fk-button-primary-border-color, transparent)}:host.fk-button--primary:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-primary-bg-hover, var(--fk-color-primary-hover, #0670e0))}:host.fk-button--primary:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-primary-bg-active, var(--fk-color-primary-active, #055fc3))}:host.fk-button--secondary .fk-button__native{background-color:var(--fk-button-secondary-bg, transparent);color:var(--fk-button-secondary-color, var(--fk-color-primary, #0a84ff));border-color:var(--fk-button-secondary-border-color, var(--fk-color-border, #d9e2ee))}:host.fk-button--secondary:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-secondary-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}:host.fk-button--secondary:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-secondary-bg-active, var(--fk-color-border, #d9e2ee))}:host.fk-button--outline .fk-button__native{background-color:var(--fk-button-outline-bg, transparent);color:var(--fk-button-outline-color, var(--fk-color-primary, #0a84ff));border-color:var(--fk-button-outline-border-color, var(--fk-color-border, #d9e2ee))}:host.fk-button--outline:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-outline-bg-hover, var(--fk-color-surface-muted, #f7f9fb))}:host.fk-button--outline:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-outline-bg-active, var(--fk-color-border, #d9e2ee))}:host.fk-button--danger .fk-button__native{background-color:var(--fk-button-danger-bg, var(--fk-color-danger, #e02424));color:var(--fk-button-danger-color, var(--fk-color-surface, #ffffff));border-color:var(--fk-button-danger-border-color, transparent)}:host.fk-button--danger:not(.fk-button--disabled) .fk-button__native:hover{background-color:var(--fk-button-danger-bg-hover, #b91c1c)}:host.fk-button--danger:not(.fk-button--disabled) .fk-button__native:active{background-color:var(--fk-button-danger-bg-active, #991b1b)}:host.fk-button--disabled .fk-button__native{opacity:var(--fk-button-opacity-disabled, .6);cursor:var(--fk-button-cursor-disabled, not-allowed)}\n"] }]
95
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], iconStartRef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FK_BUTTON_ICON_START), { isSignal: true }] }], iconEndRef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FK_BUTTON_ICON_END), { isSignal: true }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedBy", required: false }] }], hostClass: [{
96
+ type: HostBinding,
97
+ args: ['class']
98
+ }], ariaDisabledAttr: [{
99
+ type: HostBinding,
100
+ args: ['attr.aria-disabled']
101
+ }] } });
102
+
103
+ /**
104
+ * Generated bundle index. Do not edit.
105
+ */
106
+
107
+ export { ButtonComponent, FK_BUTTON_ICON_END, FK_BUTTON_ICON_START, FkButtonIconEndDirective, FkButtonIconStartDirective };
108
+ //# sourceMappingURL=frame-kit-ui-ng-ui-button.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-kit-ui-ng-ui-button.mjs","sources":["../../../../packages/ui-ng/ui/button/button-icon.directive.ts","../../../../packages/ui-ng/ui/button/button.component.ts","../../../../packages/ui-ng/ui/button/button.component.html","../../../../packages/ui-ng/ui/button/frame-kit-ui-ng-ui-button.ts"],"sourcesContent":["import { Directive, InjectionToken } from '@angular/core';\n\nexport const FK_BUTTON_ICON_START =\n new InjectionToken<FkButtonIconStartDirective>('FK_BUTTON_ICON_START');\n\nexport const FK_BUTTON_ICON_END = new InjectionToken<FkButtonIconEndDirective>(\n 'FK_BUTTON_ICON_END',\n);\n\n@Directive({\n selector: '[fkButtonIconStart]',\n standalone: true,\n providers: [\n { provide: FK_BUTTON_ICON_START, useExisting: FkButtonIconStartDirective },\n ],\n host: {\n 'aria-hidden': 'true',\n },\n})\nexport class FkButtonIconStartDirective {}\n\n@Directive({\n selector: '[fkButtonIconEnd]',\n standalone: true,\n providers: [\n { provide: FK_BUTTON_ICON_END, useExisting: FkButtonIconEndDirective },\n ],\n host: {\n 'aria-hidden': 'true',\n },\n})\nexport class FkButtonIconEndDirective {}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n HostBinding,\n input,\n} from '@angular/core';\n\nimport { LoaderComponent } from '@frame-kit/ui-ng/ui/loader';\nimport type { ButtonSize, ButtonType, ButtonVariant } from './button.types';\nimport {\n FK_BUTTON_ICON_END,\n FK_BUTTON_ICON_START,\n} from './button-icon.directive';\n\n@Component({\n selector: 'fk-button',\n standalone: true,\n imports: [LoaderComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './button.component.html',\n styleUrl: './button.component.scss',\n})\nexport class ButtonComponent {\n // ===== BEHAVIOR =====\n /** Visual style variant of the button (primary, secondary, ghost, etc.). */\n readonly variant = input<ButtonVariant>('primary');\n /** Size of the button, affecting padding and font size. */\n readonly size = input<ButtonSize>('md');\n /** When true, shows a spinner and disables interaction. */\n readonly loading = input<boolean>(false);\n /** When true, prevents interaction and applies disabled styling. */\n readonly disabled = input<boolean>(false);\n /** HTML type attribute forwarded to the inner `<button>` element. */\n readonly type = input<ButtonType>('button');\n /** When true, the button stretches to fill its container width. */\n readonly fullWidth = input<boolean>(false);\n\n // ===== CONTENT CHILDREN =====\n readonly iconStartRef = contentChild(FK_BUTTON_ICON_START);\n readonly iconEndRef = contentChild(FK_BUTTON_ICON_END);\n\n // ===== BASE PROPS =====\n readonly id = input<string | null>(null);\n readonly className = input<string>('');\n readonly ariaLabel = input<string | null>(null);\n readonly ariaDescribedBy = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly isDisabled = computed(() => this.disabled() || this.loading());\n\n readonly classes = computed(() => {\n return [\n 'fk-button',\n `fk-button--${this.variant()}`,\n `fk-button--${this.size()}`,\n this.isDisabled() ? 'fk-button--disabled' : '',\n this.loading() ? 'fk-button--loading' : '',\n this.fullWidth() ? 'fk-button--full-width' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.aria-disabled')\n get ariaDisabledAttr(): string | null {\n return this.isDisabled() ? 'true' : null;\n }\n}\n","<button\n class=\"fk-button__native\"\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n>\n @if (loading()) {\n <fk-loader\n className=\"fk-button__loader\"\n size=\"sm\"\n color=\"inherit\"\n ariaLabel=\"Loading\"\n ></fk-loader>\n }\n <span\n class=\"fk-button__content\"\n [class.fk-button__content--hidden]=\"loading()\"\n >\n <ng-content select=\"[fkButtonIconStart]\" />\n <ng-content />\n <ng-content select=\"[fkButtonIconEnd]\" />\n </span>\n</button>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { HeadlineComponent } from '@frame-kit/ui-ng/core/headline';
4
+
5
+ class CalloutComponent {
6
+ // ===== INPUTS =====
7
+ /** Optional title rendered as a headline above the projected content. */
8
+ title = input(null, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
9
+ /** Text alignment applied to the callout body. */
10
+ align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
11
+ /** Custom background color applied via a CSS custom property. */
12
+ backgroundColor = input(null, ...(ngDevMode ? [{ debugName: "backgroundColor" }] : /* istanbul ignore next */ []));
13
+ /** Custom border color applied via a CSS custom property. */
14
+ borderColor = input(null, ...(ngDevMode ? [{ debugName: "borderColor" }] : /* istanbul ignore next */ []));
15
+ // ===== BASE PROPS =====
16
+ className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
17
+ // ===== COMPUTED =====
18
+ classes = computed(() => {
19
+ return ['fk-callout', this.className()].filter(Boolean).join(' ');
20
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
21
+ get hostClass() {
22
+ return this.classes();
23
+ }
24
+ get hostBg() {
25
+ return this.backgroundColor();
26
+ }
27
+ get hostBorderColor() {
28
+ return this.borderColor();
29
+ }
30
+ get hostTextAlign() {
31
+ return this.align() === 'start' ? null : this.align();
32
+ }
33
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CalloutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
34
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CalloutComponent, isStandalone: true, selector: "fk-callout", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, borderColor: { classPropertyName: "borderColor", publicName: "borderColor", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "style.--fk-callout-bg": "this.hostBg", "style.--fk-callout-border-color": "this.hostBorderColor", "style.text-align": "this.hostTextAlign" } }, ngImport: i0, template: "@if (title()) {\n <fk-headline [level]=\"6\">{{ title() }}</fk-headline>\n}\n\n<p class=\"fk-callout__description\">\n <ng-content />\n</p>\n", styles: [":host{display:block;padding:var(--fk-callout-padding, var(--fk-rhythm-4, 1rem));background-color:var(--fk-callout-bg, var(--fk-color-surface-muted, #f7f9fb));border:1px solid var(--fk-callout-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-callout-border-radius, var(--fk-radius-md, .375rem));font-size:var(--fk-callout-font-size, var(--fk-typography-small-font-size, .8125rem));--fk-typography-h6-font-size: var(--fk-callout-title-font-size, inherit)}fk-headline+.fk-callout__description{margin-block-start:var(--fk-callout-title-gap, var(--fk-rhythm-2, .5rem))}.fk-callout__description{margin:0;color:var(--fk-text-color-muted, #6b7280);line-height:var(--fk-typography-small-line-height, 1.4);letter-spacing:var(--fk-typography-small-letter-spacing, .01em)}\n"], dependencies: [{ kind: "component", type: HeadlineComponent, selector: "fk-headline", inputs: ["ariaLabel", "className", "fontSize", "id", "level", "variant", "visuallyHidden"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
35
+ }
36
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CalloutComponent, decorators: [{
37
+ type: Component,
38
+ args: [{ selector: 'fk-callout', standalone: true, imports: [HeadlineComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (title()) {\n <fk-headline [level]=\"6\">{{ title() }}</fk-headline>\n}\n\n<p class=\"fk-callout__description\">\n <ng-content />\n</p>\n", styles: [":host{display:block;padding:var(--fk-callout-padding, var(--fk-rhythm-4, 1rem));background-color:var(--fk-callout-bg, var(--fk-color-surface-muted, #f7f9fb));border:1px solid var(--fk-callout-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-callout-border-radius, var(--fk-radius-md, .375rem));font-size:var(--fk-callout-font-size, var(--fk-typography-small-font-size, .8125rem));--fk-typography-h6-font-size: var(--fk-callout-title-font-size, inherit)}fk-headline+.fk-callout__description{margin-block-start:var(--fk-callout-title-gap, var(--fk-rhythm-2, .5rem))}.fk-callout__description{margin:0;color:var(--fk-text-color-muted, #6b7280);line-height:var(--fk-typography-small-line-height, 1.4);letter-spacing:var(--fk-typography-small-letter-spacing, .01em)}\n"] }]
39
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], borderColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderColor", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], hostClass: [{
40
+ type: HostBinding,
41
+ args: ['class']
42
+ }], hostBg: [{
43
+ type: HostBinding,
44
+ args: ['style.--fk-callout-bg']
45
+ }], hostBorderColor: [{
46
+ type: HostBinding,
47
+ args: ['style.--fk-callout-border-color']
48
+ }], hostTextAlign: [{
49
+ type: HostBinding,
50
+ args: ['style.text-align']
51
+ }] } });
52
+
53
+ /**
54
+ * Generated bundle index. Do not edit.
55
+ */
56
+
57
+ export { CalloutComponent };
58
+ //# sourceMappingURL=frame-kit-ui-ng-ui-callout.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-kit-ui-ng-ui-callout.mjs","sources":["../../../../packages/ui-ng/ui/callout/callout.component.ts","../../../../packages/ui-ng/ui/callout/callout.component.html","../../../../packages/ui-ng/ui/callout/frame-kit-ui-ng-ui-callout.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\nimport { HeadlineComponent } from '@frame-kit/ui-ng/core/headline';\nimport type { TextAlign } from '@frame-kit/ui-ng/core/text';\n\n@Component({\n selector: 'fk-callout',\n standalone: true,\n imports: [HeadlineComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './callout.component.html',\n styleUrl: './callout.component.scss',\n})\nexport class CalloutComponent {\n // ===== INPUTS =====\n /** Optional title rendered as a headline above the projected content. */\n readonly title = input<string | null>(null);\n /** Text alignment applied to the callout body. */\n readonly align = input<TextAlign>('start');\n /** Custom background color applied via a CSS custom property. */\n readonly backgroundColor = input<string | null>(null);\n /** Custom border color applied via a CSS custom property. */\n readonly borderColor = input<string | null>(null);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return ['fk-callout', this.className()].filter(Boolean).join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('style.--fk-callout-bg')\n get hostBg() {\n return this.backgroundColor();\n }\n\n @HostBinding('style.--fk-callout-border-color')\n get hostBorderColor() {\n return this.borderColor();\n }\n\n @HostBinding('style.text-align')\n get hostTextAlign() {\n return this.align() === 'start' ? null : this.align();\n }\n}\n","@if (title()) {\n <fk-headline [level]=\"6\">{{ title() }}</fk-headline>\n}\n\n<p class=\"fk-callout__description\">\n <ng-content />\n</p>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAmBa,gBAAgB,CAAA;;;AAGlB,IAAA,KAAK,GAAG,KAAK,CAAgB,IAAI,4EAAC;;AAElC,IAAA,KAAK,GAAG,KAAK,CAAY,OAAO,4EAAC;;AAEjC,IAAA,eAAe,GAAG,KAAK,CAAgB,IAAI,sFAAC;;AAE5C,IAAA,WAAW,GAAG,KAAK,CAAgB,IAAI,kFAAC;;AAGxC,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;;AAG7B,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AAC/B,QAAA,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AACnE,IAAA,CAAC,8EAAC;AAEF,IAAA,IACI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE;IACvB;AAEA,IAAA,IACI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,eAAe,EAAE;IAC/B;AAEA,IAAA,IACI,eAAe,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,WAAW,EAAE;IAC3B;AAEA,IAAA,IACI,aAAa,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE;IACvD;uGArCW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAhB,gBAAgB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,uBAAA,EAAA,aAAA,EAAA,iCAAA,EAAA,sBAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECnB7B,iJAOA,EAAA,MAAA,EAAA,CAAA,ixBAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDOY,iBAAiB,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,EAAA,WAAA,EAAA,UAAA,EAAA,IAAA,EAAA,OAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAKhB,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAR5B,SAAS;+BACE,YAAY,EAAA,UAAA,EACV,IAAI,EAAA,OAAA,EACP,CAAC,iBAAiB,CAAC,EAAA,eAAA,EACX,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,iJAAA,EAAA,MAAA,EAAA,CAAA,ixBAAA,CAAA,EAAA;;sBAuB9C,WAAW;uBAAC,OAAO;;sBAKnB,WAAW;uBAAC,uBAAuB;;sBAKnC,WAAW;uBAAC,iCAAiC;;sBAK7C,WAAW;uBAAC,kBAAkB;;;AErDjC;;AAEG;;;;"}
@@ -0,0 +1,70 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, computed, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
3
+
4
+ class CardComponent {
5
+ // ===== INPUTS =====
6
+ /** Preset size that controls the card's internal padding; also accepts any valid CSS padding string for a custom size. */
7
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
8
+ /** Alignment of the card's content along the cross axis. */
9
+ align = input('stretch', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
10
+ /** When true, the card has no background fill. */
11
+ transparent = input(false, ...(ngDevMode ? [{ debugName: "transparent" }] : /* istanbul ignore next */ []));
12
+ /** When true, the card has no border or shadow. */
13
+ borderless = input(false, ...(ngDevMode ? [{ debugName: "borderless" }] : /* istanbul ignore next */ []));
14
+ // ===== BASE PROPS =====
15
+ className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
16
+ id = input(null, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
17
+ ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
18
+ // ===== COMPUTED =====
19
+ sizePresets = ['sm', 'md', 'lg'];
20
+ isCustomSize = computed(() => !this.sizePresets.includes(this.size()), ...(ngDevMode ? [{ debugName: "isCustomSize" }] : /* istanbul ignore next */ []));
21
+ classes = computed(() => {
22
+ return [
23
+ 'fk-card',
24
+ this.isCustomSize() ? '' : `fk-card--${this.size()}`,
25
+ `fk-card--align-${this.align()}`,
26
+ this.transparent() ? 'fk-card--transparent' : '',
27
+ this.borderless() ? 'fk-card--borderless' : '',
28
+ this.className(),
29
+ ]
30
+ .filter(Boolean)
31
+ .join(' ');
32
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
33
+ get hostClass() {
34
+ return this.classes();
35
+ }
36
+ get hostPadding() {
37
+ return this.isCustomSize() ? this.size() : null;
38
+ }
39
+ get hostId() {
40
+ return this.id();
41
+ }
42
+ get hostAriaLabel() {
43
+ return this.ariaLabel();
44
+ }
45
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
46
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: CardComponent, isStandalone: true, selector: "fk-card", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, transparent: { classPropertyName: "transparent", publicName: "transparent", isSignal: true, isRequired: false, transformFunction: null }, borderless: { classPropertyName: "borderless", publicName: "borderless", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "style.padding": "this.hostPadding", "attr.id": "this.hostId", "attr.aria-label": "this.hostAriaLabel" } }, ngImport: i0, template: "<ng-content />\n", styles: [":host{display:flex;flex-direction:column;background-color:var(--fk-card-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-card-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-card-border-radius, var(--fk-radius-lg, .75rem))}:host.fk-card--transparent{background-color:transparent}:host.fk-card--borderless{border-color:transparent}:host.fk-card--align-start{align-items:flex-start}:host.fk-card--align-center{align-items:center}:host.fk-card--align-end{align-items:flex-end}:host.fk-card--align-stretch{align-items:stretch}:host.fk-card--sm{padding:var(--fk-card-padding-sm, var(--fk-rhythm-4, 1rem))}:host.fk-card--md{padding:var(--fk-card-padding-md, var(--fk-rhythm-6, 1.5rem))}:host.fk-card--lg{padding:var(--fk-card-padding-lg, var(--fk-rhythm-8, 2rem))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CardComponent, decorators: [{
49
+ type: Component,
50
+ args: [{ selector: 'fk-card', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\n", styles: [":host{display:flex;flex-direction:column;background-color:var(--fk-card-bg, var(--fk-color-surface, #ffffff));border:1px solid var(--fk-card-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-card-border-radius, var(--fk-radius-lg, .75rem))}:host.fk-card--transparent{background-color:transparent}:host.fk-card--borderless{border-color:transparent}:host.fk-card--align-start{align-items:flex-start}:host.fk-card--align-center{align-items:center}:host.fk-card--align-end{align-items:flex-end}:host.fk-card--align-stretch{align-items:stretch}:host.fk-card--sm{padding:var(--fk-card-padding-sm, var(--fk-rhythm-4, 1rem))}:host.fk-card--md{padding:var(--fk-card-padding-md, var(--fk-rhythm-6, 1.5rem))}:host.fk-card--lg{padding:var(--fk-card-padding-lg, var(--fk-rhythm-8, 2rem))}\n"] }]
51
+ }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], transparent: [{ type: i0.Input, args: [{ isSignal: true, alias: "transparent", required: false }] }], borderless: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderless", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hostClass: [{
52
+ type: HostBinding,
53
+ args: ['class']
54
+ }], hostPadding: [{
55
+ type: HostBinding,
56
+ args: ['style.padding']
57
+ }], hostId: [{
58
+ type: HostBinding,
59
+ args: ['attr.id']
60
+ }], hostAriaLabel: [{
61
+ type: HostBinding,
62
+ args: ['attr.aria-label']
63
+ }] } });
64
+
65
+ /**
66
+ * Generated bundle index. Do not edit.
67
+ */
68
+
69
+ export { CardComponent };
70
+ //# sourceMappingURL=frame-kit-ui-ng-ui-card.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-kit-ui-ng-ui-card.mjs","sources":["../../../../packages/ui-ng/ui/card/card.component.ts","../../../../packages/ui-ng/ui/card/card.component.html","../../../../packages/ui-ng/ui/card/frame-kit-ui-ng-ui-card.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\nimport type { CardAlign, CardSize } from './card.types';\n\n@Component({\n selector: 'fk-card',\n standalone: true,\n imports: [],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './card.component.html',\n styleUrl: './card.component.scss',\n})\nexport class CardComponent {\n // ===== INPUTS =====\n /** Preset size that controls the card's internal padding; also accepts any valid CSS padding string for a custom size. */\n readonly size = input<CardSize>('md');\n /** Alignment of the card's content along the cross axis. */\n readonly align = input<CardAlign>('stretch');\n /** When true, the card has no background fill. */\n readonly transparent = input<boolean>(false);\n /** When true, the card has no border or shadow. */\n readonly borderless = input<boolean>(false);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n private readonly sizePresets = ['sm', 'md', 'lg'];\n\n readonly isCustomSize = computed(\n () => !this.sizePresets.includes(this.size()),\n );\n\n readonly classes = computed(() => {\n return [\n 'fk-card',\n this.isCustomSize() ? '' : `fk-card--${this.size()}`,\n `fk-card--align-${this.align()}`,\n this.transparent() ? 'fk-card--transparent' : '',\n this.borderless() ? 'fk-card--borderless' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('style.padding')\n get hostPadding(): string | null {\n return this.isCustomSize() ? this.size() : null;\n }\n\n @HostBinding('attr.id')\n get hostId() {\n return this.id();\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel() {\n return this.ariaLabel();\n }\n}\n","<ng-content />\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;MAkBa,aAAa,CAAA;;;AAGf,IAAA,IAAI,GAAG,KAAK,CAAW,IAAI,2EAAC;;AAE5B,IAAA,KAAK,GAAG,KAAK,CAAY,SAAS,4EAAC;;AAEnC,IAAA,WAAW,GAAG,KAAK,CAAU,KAAK,kFAAC;;AAEnC,IAAA,UAAU,GAAG,KAAK,CAAU,KAAK,iFAAC;;AAGlC,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;AAC7B,IAAA,EAAE,GAAG,KAAK,CAAgB,IAAI,yEAAC;AAC/B,IAAA,SAAS,GAAG,KAAK,CAAgB,IAAI,gFAAC;;IAG9B,WAAW,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;AAExC,IAAA,YAAY,GAAG,QAAQ,CAC9B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,mFAC9C;AAEQ,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;QAC/B,OAAO;YACL,SAAS;AACT,YAAA,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,GAAG,CAAA,SAAA,EAAY,IAAI,CAAC,IAAI,EAAE,CAAA,CAAE;AACpD,YAAA,CAAA,eAAA,EAAkB,IAAI,CAAC,KAAK,EAAE,CAAA,CAAE;YAChC,IAAI,CAAC,WAAW,EAAE,GAAG,sBAAsB,GAAG,EAAE;YAChD,IAAI,CAAC,UAAU,EAAE,GAAG,qBAAqB,GAAG,EAAE;YAC9C,IAAI,CAAC,SAAS,EAAE;AACjB;aACE,MAAM,CAAC,OAAO;aACd,IAAI,CAAC,GAAG,CAAC;AACd,IAAA,CAAC,8EAAC;AAEF,IAAA,IACI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE;IACvB;AAEA,IAAA,IACI,WAAW,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI;IACjD;AAEA,IAAA,IACI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,EAAE,EAAE;IAClB;AAEA,IAAA,IACI,aAAa,GAAA;AACf,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE;IACzB;uGAtDW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAb,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,aAAa,imCClB1B,kBACA,EAAA,MAAA,EAAA,CAAA,+xBAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDiBa,aAAa,EAAA,UAAA,EAAA,CAAA;kBARzB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,SAAS,cACP,IAAI,EAAA,OAAA,EACP,EAAE,EAAA,eAAA,EACM,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,+xBAAA,CAAA,EAAA;;sBAwC9C,WAAW;uBAAC,OAAO;;sBAKnB,WAAW;uBAAC,eAAe;;sBAK3B,WAAW;uBAAC,SAAS;;sBAKrB,WAAW;uBAAC,iBAAiB;;;AErEhC;;AAEG;;;;"}
@@ -0,0 +1,113 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, signal, computed, inject, DestroyRef, HostBinding, ChangeDetectionStrategy, Component } from '@angular/core';
3
+
4
+ /**
5
+ * Displays a read-only value next to a copy-to-clipboard button.
6
+ *
7
+ * Use for showing secrets (API keys, tokens), IDs, URLs, and any value the
8
+ * user will want to copy rather than re-type. After a successful copy the
9
+ * copy-button icon swaps to a confirmation for `copiedDuration` ms and a
10
+ * screen-reader announcement fires.
11
+ *
12
+ * The copy button ships with inline SVG icons for both states so the
13
+ * component works standalone. Consumers can override either icon by
14
+ * projecting their own element with the `fkCopyIcon` or `fkCopiedIcon`
15
+ * attribute selector — for example an `fk-icon` wired to their own icon
16
+ * registry:
17
+ *
18
+ * ```html
19
+ * <fk-copyable-field [value]="apiKey">
20
+ * <fk-icon fkCopyIcon name="clipboard-outline" size="sm" />
21
+ * <fk-icon fkCopiedIcon name="check-outline" size="sm" />
22
+ * </fk-copyable-field>
23
+ * ```
24
+ */
25
+ class CopyableFieldComponent {
26
+ // ===== INPUTS =====
27
+ /** The string value displayed and written to the clipboard when the user copies. */
28
+ value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
29
+ /** Optional visible label rendered above the value field. */
30
+ label = input(null, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
31
+ /** Controls the size variant of the field. */
32
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
33
+ /** When true, the value is rendered in a monospace font. */
34
+ mono = input(true, ...(ngDevMode ? [{ debugName: "mono" }] : /* istanbul ignore next */ []));
35
+ /** Accessible label for the copy button read by screen readers. */
36
+ copyAriaLabel = input('Copy to clipboard', ...(ngDevMode ? [{ debugName: "copyAriaLabel" }] : /* istanbul ignore next */ []));
37
+ /** Screen-reader announcement text emitted after a successful copy. */
38
+ copiedAnnouncement = input('Copied to clipboard', ...(ngDevMode ? [{ debugName: "copiedAnnouncement" }] : /* istanbul ignore next */ []));
39
+ /** How long in milliseconds the "copied" confirmation state is shown. */
40
+ copiedDuration = input(2000, ...(ngDevMode ? [{ debugName: "copiedDuration" }] : /* istanbul ignore next */ []));
41
+ // ===== BASE PROPS =====
42
+ className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
43
+ id = input(null, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
44
+ ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
45
+ // ===== OUTPUTS =====
46
+ /** Fires after a successful clipboard write, emitting the copied value. */
47
+ copied = output();
48
+ /** Fires when the clipboard write fails, emitting the underlying error. */
49
+ copyFailed = output();
50
+ // ===== STATE =====
51
+ _isCopied = signal(false, ...(ngDevMode ? [{ debugName: "_isCopied" }] : /* istanbul ignore next */ []));
52
+ copyTimer = null;
53
+ isCopied = this._isCopied.asReadonly();
54
+ // ===== COMPUTED =====
55
+ classes = computed(() => {
56
+ return [
57
+ 'fk-copyable-field',
58
+ `fk-copyable-field--${this.size()}`,
59
+ this.mono() ? 'fk-copyable-field--mono' : '',
60
+ this.className(),
61
+ ]
62
+ .filter(Boolean)
63
+ .join(' ');
64
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
65
+ get hostClass() {
66
+ return this.classes();
67
+ }
68
+ constructor() {
69
+ const destroyRef = inject(DestroyRef);
70
+ destroyRef.onDestroy(() => {
71
+ this.clearCopyTimer();
72
+ });
73
+ }
74
+ /** Writes the current value to the clipboard and shows the copied confirmation state. */
75
+ async copy() {
76
+ try {
77
+ await navigator.clipboard.writeText(this.value());
78
+ }
79
+ catch (error) {
80
+ this.copyFailed.emit(error);
81
+ return;
82
+ }
83
+ this._isCopied.set(true);
84
+ this.copied.emit(this.value());
85
+ this.clearCopyTimer();
86
+ this.copyTimer = setTimeout(() => {
87
+ this._isCopied.set(false);
88
+ this.copyTimer = null;
89
+ }, this.copiedDuration());
90
+ }
91
+ clearCopyTimer() {
92
+ if (this.copyTimer) {
93
+ clearTimeout(this.copyTimer);
94
+ this.copyTimer = null;
95
+ }
96
+ }
97
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CopyableFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
98
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CopyableFieldComponent, isStandalone: true, selector: "fk-copyable-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, mono: { classPropertyName: "mono", publicName: "mono", isSignal: true, isRequired: false, transformFunction: null }, copyAriaLabel: { classPropertyName: "copyAriaLabel", publicName: "copyAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, copiedAnnouncement: { classPropertyName: "copiedAnnouncement", publicName: "copiedAnnouncement", isSignal: true, isRequired: false, transformFunction: null }, copiedDuration: { classPropertyName: "copiedDuration", publicName: "copiedDuration", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { copied: "copied", copyFailed: "copyFailed" }, host: { properties: { "class": "this.hostClass" } }, ngImport: i0, template: "@if (label()) {\n <span class=\"fk-copyable-field__label\">{{ label() }}</span>\n}\n\n<div class=\"fk-copyable-field__row\">\n <span\n class=\"fk-copyable-field__value\"\n [id]=\"id() ?? undefined\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n {{ value() }}\n </span>\n\n <button\n type=\"button\"\n class=\"fk-copyable-field__action\"\n [attr.aria-label]=\"copyAriaLabel()\"\n (click)=\"copy()\"\n >\n @if (isCopied()) {\n <ng-content select=\"[fkCopiedIcon]\">\n <svg\n class=\"fk-copyable-field__icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M3 8.5l3 3L13 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n } @else {\n <ng-content select=\"[fkCopyIcon]\">\n <svg\n class=\"fk-copyable-field__icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <rect\n x=\"5.25\"\n y=\"5.25\"\n width=\"8.5\"\n height=\"8.5\"\n rx=\"1.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n />\n <path\n d=\"M10 5.25V3.75A1.5 1.5 0 0 0 8.5 2.25h-5A1.5 1.5 0 0 0 2 3.75v5A1.5 1.5 0 0 0 3.5 10.25H5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n />\n </svg>\n </ng-content>\n }\n </button>\n</div>\n\n<span class=\"fk-copyable-field__sr-only\" role=\"status\" aria-live=\"polite\">\n @if (isCopied()) {\n {{ copiedAnnouncement() }}\n }\n</span>\n", styles: [":host{display:block}.fk-copyable-field__label{display:block;margin-bottom:var(--fk-copyable-field-label-gap, var(--fk-rhythm-1, .25rem));font-size:var(--fk-copyable-field-label-font-size, var(--fk-typography-small-font-size, .8125rem));font-weight:var(--fk-copyable-field-label-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-copyable-field-label-color, var(--fk-color-muted, #8a98a8))}.fk-copyable-field__row{display:flex;align-items:center;gap:var(--fk-copyable-field-gap, var(--fk-rhythm-2, .5rem));background:var(--fk-copyable-field-bg, var(--fk-color-surface-muted, #f7f9fb));border:1px solid var(--fk-copyable-field-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-copyable-field-radius, var(--fk-radius-md, .5rem))}.fk-copyable-field__value{flex:1;min-width:0;color:var(--fk-copyable-field-value-color, var(--fk-color-text, #1f2d3d));word-break:break-all}.fk-copyable-field__action{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;padding:var(--fk-copyable-field-action-padding, var(--fk-rhythm-1, .25rem));color:var(--fk-copyable-field-action-color, var(--fk-color-muted, #8a98a8));background:transparent;border:none;border-radius:var(--fk-copyable-field-action-radius, var(--fk-radius-sm, .25rem));cursor:pointer;transition:color .15s,background-color .15s}.fk-copyable-field__action:hover{color:var(--fk-copyable-field-action-color-hover, var(--fk-color-text, #1f2d3d));background:var(--fk-copyable-field-action-bg-hover, var(--fk-color-surface-dim, #f1f4f8))}.fk-copyable-field__action:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-copyable-field__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host.fk-copyable-field--sm .fk-copyable-field__row{padding:var(--fk-copyable-field-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-copyable-field--sm .fk-copyable-field__value{font-size:var(--fk-copyable-field-font-size-sm, var(--fk-typography-caption-font-size, .75rem))}:host.fk-copyable-field--md .fk-copyable-field__row{padding:var(--fk-copyable-field-padding-md, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem))}:host.fk-copyable-field--md .fk-copyable-field__value{font-size:var(--fk-copyable-field-font-size-md, var(--fk-typography-small-font-size, .8125rem))}:host.fk-copyable-field--lg .fk-copyable-field__row{padding:var(--fk-copyable-field-padding-lg, var(--fk-rhythm-3, .75rem) var(--fk-rhythm-4, 1rem))}:host.fk-copyable-field--lg .fk-copyable-field__value{font-size:var(--fk-copyable-field-font-size-lg, var(--fk-typography-body-font-size, .9375rem))}:host.fk-copyable-field--mono .fk-copyable-field__value{font-family:var(--fk-copyable-field-mono-font-family, var(--fk-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
99
+ }
100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CopyableFieldComponent, decorators: [{
101
+ type: Component,
102
+ args: [{ selector: 'fk-copyable-field', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (label()) {\n <span class=\"fk-copyable-field__label\">{{ label() }}</span>\n}\n\n<div class=\"fk-copyable-field__row\">\n <span\n class=\"fk-copyable-field__value\"\n [id]=\"id() ?? undefined\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n {{ value() }}\n </span>\n\n <button\n type=\"button\"\n class=\"fk-copyable-field__action\"\n [attr.aria-label]=\"copyAriaLabel()\"\n (click)=\"copy()\"\n >\n @if (isCopied()) {\n <ng-content select=\"[fkCopiedIcon]\">\n <svg\n class=\"fk-copyable-field__icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M3 8.5l3 3L13 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n } @else {\n <ng-content select=\"[fkCopyIcon]\">\n <svg\n class=\"fk-copyable-field__icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <rect\n x=\"5.25\"\n y=\"5.25\"\n width=\"8.5\"\n height=\"8.5\"\n rx=\"1.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n />\n <path\n d=\"M10 5.25V3.75A1.5 1.5 0 0 0 8.5 2.25h-5A1.5 1.5 0 0 0 2 3.75v5A1.5 1.5 0 0 0 3.5 10.25H5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n />\n </svg>\n </ng-content>\n }\n </button>\n</div>\n\n<span class=\"fk-copyable-field__sr-only\" role=\"status\" aria-live=\"polite\">\n @if (isCopied()) {\n {{ copiedAnnouncement() }}\n }\n</span>\n", styles: [":host{display:block}.fk-copyable-field__label{display:block;margin-bottom:var(--fk-copyable-field-label-gap, var(--fk-rhythm-1, .25rem));font-size:var(--fk-copyable-field-label-font-size, var(--fk-typography-small-font-size, .8125rem));font-weight:var(--fk-copyable-field-label-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-copyable-field-label-color, var(--fk-color-muted, #8a98a8))}.fk-copyable-field__row{display:flex;align-items:center;gap:var(--fk-copyable-field-gap, var(--fk-rhythm-2, .5rem));background:var(--fk-copyable-field-bg, var(--fk-color-surface-muted, #f7f9fb));border:1px solid var(--fk-copyable-field-border-color, var(--fk-color-border, #d9e2ee));border-radius:var(--fk-copyable-field-radius, var(--fk-radius-md, .5rem))}.fk-copyable-field__value{flex:1;min-width:0;color:var(--fk-copyable-field-value-color, var(--fk-color-text, #1f2d3d));word-break:break-all}.fk-copyable-field__action{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;padding:var(--fk-copyable-field-action-padding, var(--fk-rhythm-1, .25rem));color:var(--fk-copyable-field-action-color, var(--fk-color-muted, #8a98a8));background:transparent;border:none;border-radius:var(--fk-copyable-field-action-radius, var(--fk-radius-sm, .25rem));cursor:pointer;transition:color .15s,background-color .15s}.fk-copyable-field__action:hover{color:var(--fk-copyable-field-action-color-hover, var(--fk-color-text, #1f2d3d));background:var(--fk-copyable-field-action-bg-hover, var(--fk-color-surface-dim, #f1f4f8))}.fk-copyable-field__action:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-copyable-field__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host.fk-copyable-field--sm .fk-copyable-field__row{padding:var(--fk-copyable-field-padding-sm, var(--fk-rhythm-1, .25rem) var(--fk-rhythm-2, .5rem))}:host.fk-copyable-field--sm .fk-copyable-field__value{font-size:var(--fk-copyable-field-font-size-sm, var(--fk-typography-caption-font-size, .75rem))}:host.fk-copyable-field--md .fk-copyable-field__row{padding:var(--fk-copyable-field-padding-md, var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem))}:host.fk-copyable-field--md .fk-copyable-field__value{font-size:var(--fk-copyable-field-font-size-md, var(--fk-typography-small-font-size, .8125rem))}:host.fk-copyable-field--lg .fk-copyable-field__row{padding:var(--fk-copyable-field-padding-lg, var(--fk-rhythm-3, .75rem) var(--fk-rhythm-4, 1rem))}:host.fk-copyable-field--lg .fk-copyable-field__value{font-size:var(--fk-copyable-field-font-size-lg, var(--fk-typography-body-font-size, .9375rem))}:host.fk-copyable-field--mono .fk-copyable-field__value{font-family:var(--fk-copyable-field-mono-font-family, var(--fk-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace))}\n"] }]
103
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], mono: [{ type: i0.Input, args: [{ isSignal: true, alias: "mono", required: false }] }], copyAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyAriaLabel", required: false }] }], copiedAnnouncement: [{ type: i0.Input, args: [{ isSignal: true, alias: "copiedAnnouncement", required: false }] }], copiedDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "copiedDuration", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], copied: [{ type: i0.Output, args: ["copied"] }], copyFailed: [{ type: i0.Output, args: ["copyFailed"] }], hostClass: [{
104
+ type: HostBinding,
105
+ args: ['class']
106
+ }] } });
107
+
108
+ /**
109
+ * Generated bundle index. Do not edit.
110
+ */
111
+
112
+ export { CopyableFieldComponent };
113
+ //# sourceMappingURL=frame-kit-ui-ng-ui-copyable-field.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-kit-ui-ng-ui-copyable-field.mjs","sources":["../../../../packages/ui-ng/ui/copyable-field/copyable-field.component.ts","../../../../packages/ui-ng/ui/copyable-field/copyable-field.component.html","../../../../packages/ui-ng/ui/copyable-field/frame-kit-ui-ng-ui-copyable-field.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n HostBinding,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport type { CopyableFieldSize } from './copyable-field.types';\n\n/**\n * Displays a read-only value next to a copy-to-clipboard button.\n *\n * Use for showing secrets (API keys, tokens), IDs, URLs, and any value the\n * user will want to copy rather than re-type. After a successful copy the\n * copy-button icon swaps to a confirmation for `copiedDuration` ms and a\n * screen-reader announcement fires.\n *\n * The copy button ships with inline SVG icons for both states so the\n * component works standalone. Consumers can override either icon by\n * projecting their own element with the `fkCopyIcon` or `fkCopiedIcon`\n * attribute selector — for example an `fk-icon` wired to their own icon\n * registry:\n *\n * ```html\n * <fk-copyable-field [value]=\"apiKey\">\n * <fk-icon fkCopyIcon name=\"clipboard-outline\" size=\"sm\" />\n * <fk-icon fkCopiedIcon name=\"check-outline\" size=\"sm\" />\n * </fk-copyable-field>\n * ```\n */\n@Component({\n selector: 'fk-copyable-field',\n standalone: true,\n imports: [],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './copyable-field.component.html',\n styleUrl: './copyable-field.component.scss',\n})\nexport class CopyableFieldComponent {\n // ===== INPUTS =====\n /** The string value displayed and written to the clipboard when the user copies. */\n readonly value = input.required<string>();\n /** Optional visible label rendered above the value field. */\n readonly label = input<string | null>(null);\n /** Controls the size variant of the field. */\n readonly size = input<CopyableFieldSize>('md');\n /** When true, the value is rendered in a monospace font. */\n readonly mono = input<boolean>(true);\n /** Accessible label for the copy button read by screen readers. */\n readonly copyAriaLabel = input<string>('Copy to clipboard');\n /** Screen-reader announcement text emitted after a successful copy. */\n readonly copiedAnnouncement = input<string>('Copied to clipboard');\n /** How long in milliseconds the \"copied\" confirmation state is shown. */\n readonly copiedDuration = input<number>(2000);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== OUTPUTS =====\n /** Fires after a successful clipboard write, emitting the copied value. */\n readonly copied = output<string>();\n /** Fires when the clipboard write fails, emitting the underlying error. */\n readonly copyFailed = output<unknown>();\n\n // ===== STATE =====\n private readonly _isCopied = signal(false);\n private copyTimer: ReturnType<typeof setTimeout> | null = null;\n\n readonly isCopied = this._isCopied.asReadonly();\n\n // ===== COMPUTED =====\n readonly classes = computed(() => {\n return [\n 'fk-copyable-field',\n `fk-copyable-field--${this.size()}`,\n this.mono() ? 'fk-copyable-field--mono' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n\n destroyRef.onDestroy(() => {\n this.clearCopyTimer();\n });\n }\n\n /** Writes the current value to the clipboard and shows the copied confirmation state. */\n async copy(): Promise<void> {\n try {\n await navigator.clipboard.writeText(this.value());\n } catch (error) {\n this.copyFailed.emit(error);\n\n return;\n }\n\n this._isCopied.set(true);\n this.copied.emit(this.value());\n\n this.clearCopyTimer();\n\n this.copyTimer = setTimeout(() => {\n this._isCopied.set(false);\n this.copyTimer = null;\n }, this.copiedDuration());\n }\n\n private clearCopyTimer(): void {\n if (this.copyTimer) {\n clearTimeout(this.copyTimer);\n this.copyTimer = null;\n }\n }\n}\n","@if (label()) {\n <span class=\"fk-copyable-field__label\">{{ label() }}</span>\n}\n\n<div class=\"fk-copyable-field__row\">\n <span\n class=\"fk-copyable-field__value\"\n [id]=\"id() ?? undefined\"\n [attr.aria-label]=\"ariaLabel()\"\n >\n {{ value() }}\n </span>\n\n <button\n type=\"button\"\n class=\"fk-copyable-field__action\"\n [attr.aria-label]=\"copyAriaLabel()\"\n (click)=\"copy()\"\n >\n @if (isCopied()) {\n <ng-content select=\"[fkCopiedIcon]\">\n <svg\n class=\"fk-copyable-field__icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M3 8.5l3 3L13 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n } @else {\n <ng-content select=\"[fkCopyIcon]\">\n <svg\n class=\"fk-copyable-field__icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <rect\n x=\"5.25\"\n y=\"5.25\"\n width=\"8.5\"\n height=\"8.5\"\n rx=\"1.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n />\n <path\n d=\"M10 5.25V3.75A1.5 1.5 0 0 0 8.5 2.25h-5A1.5 1.5 0 0 0 2 3.75v5A1.5 1.5 0 0 0 3.5 10.25H5\"\n stroke=\"currentColor\"\n stroke-width=\"1.25\"\n stroke-linecap=\"round\"\n />\n </svg>\n </ng-content>\n }\n </button>\n</div>\n\n<span class=\"fk-copyable-field__sr-only\" role=\"status\" aria-live=\"polite\">\n @if (isCopied()) {\n {{ copiedAnnouncement() }}\n }\n</span>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}