@hyalo/angular 0.0.0-stage → 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 (229) hide show
  1. package/CHANGELOG.md +95 -0
  2. package/LICENSE +21 -0
  3. package/README.md +45 -2
  4. package/fesm2022/hyalo-angular-accordion.mjs +230 -0
  5. package/fesm2022/hyalo-angular-accordion.mjs.map +1 -0
  6. package/fesm2022/hyalo-angular-alert.mjs +171 -0
  7. package/fesm2022/hyalo-angular-alert.mjs.map +1 -0
  8. package/fesm2022/hyalo-angular-aspect-ratio.mjs +64 -0
  9. package/fesm2022/hyalo-angular-aspect-ratio.mjs.map +1 -0
  10. package/fesm2022/hyalo-angular-avatar.mjs +169 -0
  11. package/fesm2022/hyalo-angular-avatar.mjs.map +1 -0
  12. package/fesm2022/hyalo-angular-badge.mjs +268 -0
  13. package/fesm2022/hyalo-angular-badge.mjs.map +1 -0
  14. package/fesm2022/hyalo-angular-bento.mjs +132 -0
  15. package/fesm2022/hyalo-angular-bento.mjs.map +1 -0
  16. package/fesm2022/hyalo-angular-blocks.mjs +985 -0
  17. package/fesm2022/hyalo-angular-blocks.mjs.map +1 -0
  18. package/fesm2022/hyalo-angular-border-beam.mjs +73 -0
  19. package/fesm2022/hyalo-angular-border-beam.mjs.map +1 -0
  20. package/fesm2022/hyalo-angular-breadcrumb.mjs +77 -0
  21. package/fesm2022/hyalo-angular-breadcrumb.mjs.map +1 -0
  22. package/fesm2022/hyalo-angular-button-group.mjs +90 -0
  23. package/fesm2022/hyalo-angular-button-group.mjs.map +1 -0
  24. package/fesm2022/hyalo-angular-button.mjs +204 -0
  25. package/fesm2022/hyalo-angular-button.mjs.map +1 -0
  26. package/fesm2022/hyalo-angular-card.mjs +221 -0
  27. package/fesm2022/hyalo-angular-card.mjs.map +1 -0
  28. package/fesm2022/hyalo-angular-carousel.mjs +709 -0
  29. package/fesm2022/hyalo-angular-carousel.mjs.map +1 -0
  30. package/fesm2022/hyalo-angular-chapter-nav.mjs +336 -0
  31. package/fesm2022/hyalo-angular-chapter-nav.mjs.map +1 -0
  32. package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs +5 -0
  33. package/fesm2022/hyalo-angular-chart-engine-DSJop6He.mjs.map +1 -0
  34. package/fesm2022/hyalo-angular-chart.mjs +391 -0
  35. package/fesm2022/hyalo-angular-chart.mjs.map +1 -0
  36. package/fesm2022/hyalo-angular-choice.mjs +789 -0
  37. package/fesm2022/hyalo-angular-choice.mjs.map +1 -0
  38. package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs +40 -0
  39. package/fesm2022/hyalo-angular-code-block-highlight-B20d5C76.mjs.map +1 -0
  40. package/fesm2022/hyalo-angular-code-block.mjs +161 -0
  41. package/fesm2022/hyalo-angular-code-block.mjs.map +1 -0
  42. package/fesm2022/hyalo-angular-command.mjs +193 -0
  43. package/fesm2022/hyalo-angular-command.mjs.map +1 -0
  44. package/fesm2022/hyalo-angular-copy.mjs +138 -0
  45. package/fesm2022/hyalo-angular-copy.mjs.map +1 -0
  46. package/fesm2022/hyalo-angular-core.mjs +424 -0
  47. package/fesm2022/hyalo-angular-core.mjs.map +1 -0
  48. package/fesm2022/hyalo-angular-description-list.mjs +57 -0
  49. package/fesm2022/hyalo-angular-description-list.mjs.map +1 -0
  50. package/fesm2022/hyalo-angular-dialog.mjs +600 -0
  51. package/fesm2022/hyalo-angular-dialog.mjs.map +1 -0
  52. package/fesm2022/hyalo-angular-divider.mjs +66 -0
  53. package/fesm2022/hyalo-angular-divider.mjs.map +1 -0
  54. package/fesm2022/hyalo-angular-empty-state.mjs +123 -0
  55. package/fesm2022/hyalo-angular-empty-state.mjs.map +1 -0
  56. package/fesm2022/hyalo-angular-field.mjs +344 -0
  57. package/fesm2022/hyalo-angular-field.mjs.map +1 -0
  58. package/fesm2022/hyalo-angular-filter.mjs +309 -0
  59. package/fesm2022/hyalo-angular-filter.mjs.map +1 -0
  60. package/fesm2022/hyalo-angular-hotspot.mjs +225 -0
  61. package/fesm2022/hyalo-angular-hotspot.mjs.map +1 -0
  62. package/fesm2022/hyalo-angular-hover-card.mjs +233 -0
  63. package/fesm2022/hyalo-angular-hover-card.mjs.map +1 -0
  64. package/fesm2022/hyalo-angular-icon.mjs +385 -0
  65. package/fesm2022/hyalo-angular-icon.mjs.map +1 -0
  66. package/fesm2022/hyalo-angular-image-compare.mjs +168 -0
  67. package/fesm2022/hyalo-angular-image-compare.mjs.map +1 -0
  68. package/fesm2022/hyalo-angular-interaction.mjs +446 -0
  69. package/fesm2022/hyalo-angular-interaction.mjs.map +1 -0
  70. package/fesm2022/hyalo-angular-kbd.mjs +41 -0
  71. package/fesm2022/hyalo-angular-kbd.mjs.map +1 -0
  72. package/fesm2022/hyalo-angular-lightbox.mjs +228 -0
  73. package/fesm2022/hyalo-angular-lightbox.mjs.map +1 -0
  74. package/fesm2022/hyalo-angular-link.mjs +42 -0
  75. package/fesm2022/hyalo-angular-link.mjs.map +1 -0
  76. package/fesm2022/hyalo-angular-list.mjs +131 -0
  77. package/fesm2022/hyalo-angular-list.mjs.map +1 -0
  78. package/fesm2022/hyalo-angular-marquee.mjs +197 -0
  79. package/fesm2022/hyalo-angular-marquee.mjs.map +1 -0
  80. package/fesm2022/hyalo-angular-menu.mjs +423 -0
  81. package/fesm2022/hyalo-angular-menu.mjs.map +1 -0
  82. package/fesm2022/hyalo-angular-mesh.mjs +126 -0
  83. package/fesm2022/hyalo-angular-mesh.mjs.map +1 -0
  84. package/fesm2022/hyalo-angular-motion.mjs +620 -0
  85. package/fesm2022/hyalo-angular-motion.mjs.map +1 -0
  86. package/fesm2022/hyalo-angular-navbar.mjs +343 -0
  87. package/fesm2022/hyalo-angular-navbar.mjs.map +1 -0
  88. package/fesm2022/hyalo-angular-navigation-menu.mjs +222 -0
  89. package/fesm2022/hyalo-angular-navigation-menu.mjs.map +1 -0
  90. package/fesm2022/hyalo-angular-number-ticker.mjs +174 -0
  91. package/fesm2022/hyalo-angular-number-ticker.mjs.map +1 -0
  92. package/fesm2022/hyalo-angular-overlay.mjs +163 -0
  93. package/fesm2022/hyalo-angular-overlay.mjs.map +1 -0
  94. package/fesm2022/hyalo-angular-pagination.mjs +187 -0
  95. package/fesm2022/hyalo-angular-pagination.mjs.map +1 -0
  96. package/fesm2022/hyalo-angular-popover-overlay-kit-6wPwnxln.mjs +3 -0
  97. package/fesm2022/hyalo-angular-popover.mjs +516 -0
  98. package/fesm2022/hyalo-angular-popover.mjs.map +1 -0
  99. package/fesm2022/hyalo-angular-progress.mjs +209 -0
  100. package/fesm2022/hyalo-angular-progress.mjs.map +1 -0
  101. package/fesm2022/hyalo-angular-progressive-blur.mjs +73 -0
  102. package/fesm2022/hyalo-angular-progressive-blur.mjs.map +1 -0
  103. package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs +186 -0
  104. package/fesm2022/hyalo-angular-refraction-renderer-5ZA-kfsA.mjs.map +1 -0
  105. package/fesm2022/hyalo-angular-refraction.mjs +178 -0
  106. package/fesm2022/hyalo-angular-refraction.mjs.map +1 -0
  107. package/fesm2022/hyalo-angular-scroll-area.mjs +93 -0
  108. package/fesm2022/hyalo-angular-scroll-area.mjs.map +1 -0
  109. package/fesm2022/hyalo-angular-scroll-to-top.mjs +127 -0
  110. package/fesm2022/hyalo-angular-scroll-to-top.mjs.map +1 -0
  111. package/fesm2022/hyalo-angular-segmented.mjs +223 -0
  112. package/fesm2022/hyalo-angular-segmented.mjs.map +1 -0
  113. package/fesm2022/hyalo-angular-select.mjs +561 -0
  114. package/fesm2022/hyalo-angular-select.mjs.map +1 -0
  115. package/fesm2022/hyalo-angular-sidebar.mjs +241 -0
  116. package/fesm2022/hyalo-angular-sidebar.mjs.map +1 -0
  117. package/fesm2022/hyalo-angular-skeleton.mjs +131 -0
  118. package/fesm2022/hyalo-angular-skeleton.mjs.map +1 -0
  119. package/fesm2022/hyalo-angular-sparkline.mjs +110 -0
  120. package/fesm2022/hyalo-angular-sparkline.mjs.map +1 -0
  121. package/fesm2022/hyalo-angular-split-text.mjs +126 -0
  122. package/fesm2022/hyalo-angular-split-text.mjs.map +1 -0
  123. package/fesm2022/hyalo-angular-stat.mjs +193 -0
  124. package/fesm2022/hyalo-angular-stat.mjs.map +1 -0
  125. package/fesm2022/hyalo-angular-stepper.mjs +254 -0
  126. package/fesm2022/hyalo-angular-stepper.mjs.map +1 -0
  127. package/fesm2022/hyalo-angular-table.mjs +335 -0
  128. package/fesm2022/hyalo-angular-table.mjs.map +1 -0
  129. package/fesm2022/hyalo-angular-tabs.mjs +324 -0
  130. package/fesm2022/hyalo-angular-tabs.mjs.map +1 -0
  131. package/fesm2022/hyalo-angular-theme.mjs +94 -0
  132. package/fesm2022/hyalo-angular-theme.mjs.map +1 -0
  133. package/fesm2022/hyalo-angular-timeline.mjs +157 -0
  134. package/fesm2022/hyalo-angular-timeline.mjs.map +1 -0
  135. package/fesm2022/hyalo-angular-toast.mjs +323 -0
  136. package/fesm2022/hyalo-angular-toast.mjs.map +1 -0
  137. package/fesm2022/hyalo-angular.mjs +2 -0
  138. package/package.json +329 -3
  139. package/styles/hyalo-core.css +25 -0
  140. package/styles/hyalo.css +17 -0
  141. package/styles/overlays/dialog.css +9 -0
  142. package/styles/overlays/popover.css +9 -0
  143. package/styles/overlays/select.css +9 -0
  144. package/styles/overlays/toast.css +8 -0
  145. package/styles/palettes/aurora.css +47 -0
  146. package/styles/palettes/ember.css +47 -0
  147. package/styles/palettes/graphite.css +47 -0
  148. package/styles/palettes/ocean.css +47 -0
  149. package/styles/palettes/orchid.css +47 -0
  150. package/styles/palettes/rose.css +47 -0
  151. package/styles/parts/card.css +49 -0
  152. package/styles/parts/dialog.css +116 -0
  153. package/styles/parts/drawer.css +124 -0
  154. package/styles/parts/field.css +44 -0
  155. package/styles/parts/glass.css +139 -0
  156. package/styles/parts/motion.css +101 -0
  157. package/styles/parts/navbar.css +55 -0
  158. package/styles/parts/popover.css +27 -0
  159. package/styles/parts/presence.css +55 -0
  160. package/styles/parts/reset.css +42 -0
  161. package/styles/parts/select.css +46 -0
  162. package/styles/parts/themes.css +105 -0
  163. package/styles/parts/toast.css +128 -0
  164. package/styles/parts/tokens.css +151 -0
  165. package/styles/parts/typography.css +81 -0
  166. package/types/hyalo-angular-accordion.d.ts +74 -0
  167. package/types/hyalo-angular-alert.d.ts +47 -0
  168. package/types/hyalo-angular-aspect-ratio.d.ts +13 -0
  169. package/types/hyalo-angular-avatar.d.ts +39 -0
  170. package/types/hyalo-angular-badge.d.ts +82 -0
  171. package/types/hyalo-angular-bento.d.ts +25 -0
  172. package/types/hyalo-angular-blocks.d.ts +272 -0
  173. package/types/hyalo-angular-border-beam.d.ts +15 -0
  174. package/types/hyalo-angular-breadcrumb.d.ts +22 -0
  175. package/types/hyalo-angular-button-group.d.ts +19 -0
  176. package/types/hyalo-angular-button.d.ts +89 -0
  177. package/types/hyalo-angular-card.d.ts +61 -0
  178. package/types/hyalo-angular-carousel.d.ts +147 -0
  179. package/types/hyalo-angular-chapter-nav.d.ts +79 -0
  180. package/types/hyalo-angular-chart.d.ts +90 -0
  181. package/types/hyalo-angular-choice.d.ts +259 -0
  182. package/types/hyalo-angular-code-block.d.ts +46 -0
  183. package/types/hyalo-angular-command.d.ts +41 -0
  184. package/types/hyalo-angular-copy.d.ts +39 -0
  185. package/types/hyalo-angular-core.d.ts +210 -0
  186. package/types/hyalo-angular-description-list.d.ts +16 -0
  187. package/types/hyalo-angular-dialog.d.ts +171 -0
  188. package/types/hyalo-angular-divider.d.ts +12 -0
  189. package/types/hyalo-angular-empty-state.d.ts +30 -0
  190. package/types/hyalo-angular-field.d.ts +141 -0
  191. package/types/hyalo-angular-filter.d.ts +122 -0
  192. package/types/hyalo-angular-hotspot.d.ts +70 -0
  193. package/types/hyalo-angular-hover-card.d.ts +47 -0
  194. package/types/hyalo-angular-icon.d.ts +122 -0
  195. package/types/hyalo-angular-image-compare.d.ts +55 -0
  196. package/types/hyalo-angular-interaction.d.ts +131 -0
  197. package/types/hyalo-angular-kbd.d.ts +5 -0
  198. package/types/hyalo-angular-lightbox.d.ts +67 -0
  199. package/types/hyalo-angular-link.d.ts +5 -0
  200. package/types/hyalo-angular-list.d.ts +30 -0
  201. package/types/hyalo-angular-marquee.d.ts +48 -0
  202. package/types/hyalo-angular-menu.d.ts +105 -0
  203. package/types/hyalo-angular-mesh.d.ts +36 -0
  204. package/types/hyalo-angular-motion.d.ts +218 -0
  205. package/types/hyalo-angular-navbar.d.ts +110 -0
  206. package/types/hyalo-angular-navigation-menu.d.ts +47 -0
  207. package/types/hyalo-angular-number-ticker.d.ts +52 -0
  208. package/types/hyalo-angular-overlay.d.ts +40 -0
  209. package/types/hyalo-angular-pagination.d.ts +59 -0
  210. package/types/hyalo-angular-popover.d.ts +152 -0
  211. package/types/hyalo-angular-progress.d.ts +46 -0
  212. package/types/hyalo-angular-progressive-blur.d.ts +14 -0
  213. package/types/hyalo-angular-refraction.d.ts +46 -0
  214. package/types/hyalo-angular-scroll-area.d.ts +18 -0
  215. package/types/hyalo-angular-scroll-to-top.d.ts +31 -0
  216. package/types/hyalo-angular-segmented.d.ts +79 -0
  217. package/types/hyalo-angular-select.d.ts +176 -0
  218. package/types/hyalo-angular-sidebar.d.ts +57 -0
  219. package/types/hyalo-angular-skeleton.d.ts +34 -0
  220. package/types/hyalo-angular-sparkline.d.ts +19 -0
  221. package/types/hyalo-angular-split-text.d.ts +24 -0
  222. package/types/hyalo-angular-stat.d.ts +56 -0
  223. package/types/hyalo-angular-stepper.d.ts +63 -0
  224. package/types/hyalo-angular-table.d.ts +125 -0
  225. package/types/hyalo-angular-tabs.d.ts +102 -0
  226. package/types/hyalo-angular-theme.d.ts +46 -0
  227. package/types/hyalo-angular-timeline.d.ts +36 -0
  228. package/types/hyalo-angular-toast.d.ts +79 -0
  229. package/types/hyalo-angular.d.ts +2 -0
@@ -0,0 +1,309 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, computed, input, model } from "@angular/core";
3
+ import { NgTemplateOutlet } from "@angular/common";
4
+ import { HyField, HyInput } from "@hyalo/angular/field";
5
+ import { HySelect } from "@hyalo/angular/select";
6
+ function encodeFilters(clauses) {
7
+ return JSON.stringify({
8
+ version: 1,
9
+ clauses
10
+ });
11
+ }
12
+ function decodeFilters(text, codec) {
13
+ const payload = JSON.parse(text);
14
+ if (!payload || typeof payload !== "object" || !("version" in payload) || payload.version !== 1 || !("clauses" in payload) || !Array.isArray(payload.clauses)) throw new Error("Unsupported filter state");
15
+ const ids = /* @__PURE__ */ new Set();
16
+ return payload.clauses.map((value) => {
17
+ if (!isFilterToken(value) || !codec.accepts(value) || ids.has(value.id)) throw new Error("Invalid or unsupported filter clause");
18
+ ids.add(value.id);
19
+ return value;
20
+ });
21
+ }
22
+ function isFilterToken(value) {
23
+ if (!value || typeof value !== "object" || !("id" in value) || typeof value.id !== "string" || !value.id || !("field" in value) || typeof value.field !== "string" || !value.field || !("operator" in value) || !("value" in value)) return false;
24
+ const data = value.value;
25
+ const scalar = (v) => typeof v === "string" || typeof v === "boolean" || typeof v === "number" && Number.isFinite(v);
26
+ if (value.operator === "eq") return scalar(data);
27
+ if (value.operator === "contains") return typeof data === "string";
28
+ if (value.operator === "in") return Array.isArray(data) && data.every(scalar);
29
+ if (value.operator !== "between") return false;
30
+ if (Array.isArray(data)) return data.length === 2 && data.every((v) => typeof v === "number" && Number.isFinite(v)) && data[0] <= data[1];
31
+ if (!data || typeof data !== "object" || !("timeZone" in data) || typeof data.timeZone !== "string" || !("kind" in data)) return false;
32
+ try {
33
+ new Intl.DateTimeFormat("en", { timeZone: data.timeZone });
34
+ } catch {
35
+ return false;
36
+ }
37
+ if (data.kind === "preset") return "preset" in data && [
38
+ "24H",
39
+ "7D",
40
+ "30D",
41
+ "1Y"
42
+ ].includes(String(data.preset));
43
+ const instant = (v) => typeof v === "string" && /^\d{4}-\d{2}-\d{2}T.*(?:Z|[+-]\d{2}:\d{2})$/.test(v) && Number.isFinite(Date.parse(v));
44
+ return data.kind === "absolute" && "start" in data && "end" in data && instant(data.start) && instant(data.end) && Date.parse(data.start) < Date.parse(data.end);
45
+ }
46
+ function resolveDateRange(value, now) {
47
+ if (!isFilterToken({
48
+ id: "range",
49
+ field: "time",
50
+ operator: "between",
51
+ value
52
+ }) || !Number.isFinite(now.getTime())) throw new Error("Invalid date range");
53
+ if (value.kind === "absolute") return {
54
+ start: value.start,
55
+ end: value.end
56
+ };
57
+ const hours = {
58
+ "24H": 24,
59
+ "7D": 168,
60
+ "30D": 720,
61
+ "1Y": 8760
62
+ }[value.preset];
63
+ return {
64
+ start: (/* @__PURE__ */ new Date(now.getTime() - hours * 36e5)).toISOString(),
65
+ end: now.toISOString()
66
+ };
67
+ }
68
+ var HyFilterBar = class HyFilterBar {
69
+ fields = input.required(...ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []);
70
+ clauses = model([], ...ngDevMode ? [{ debugName: "clauses" }] : /* istanbul ignore next */ []);
71
+ label = input("Filter results", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
72
+ clearLabel = input("Clear filters", ...ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []);
73
+ removeLabel = input("Remove", ...ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []);
74
+ anyLabel = input("Any", ...ngDevMode ? [{ debugName: "anyLabel" }] : /* istanbul ignore next */ []);
75
+ activeLabel = input("Active filters", ...ngDevMode ? [{ debugName: "activeLabel" }] : /* istanbul ignore next */ []);
76
+ view = computed(() => this.clauses().map((clause) => {
77
+ const field = this.fields().find((entry) => entry.field === clause.field);
78
+ return {
79
+ clause,
80
+ label: field?.label ?? clause.field,
81
+ text: field?.format?.(clause) ?? (typeof clause.value === "object" ? JSON.stringify(clause.value) : String(clause.value)),
82
+ editor: field?.editor,
83
+ context: {
84
+ $implicit: clause,
85
+ update: (next) => this.update(next)
86
+ }
87
+ };
88
+ }), ...ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []);
89
+ raw(field) {
90
+ const value = this.clauses().find((clause) => clause.field === field)?.value;
91
+ if (typeof value === "object" && value && !Array.isArray(value) && "kind" in value && value.kind === "preset" && "preset" in value) return String(value.preset);
92
+ return typeof value === "string" ? value : "";
93
+ }
94
+ change(field, raw) {
95
+ const existing = this.clauses().find((clause) => clause.field === field.field);
96
+ const next = raw ? field.create(existing?.id ?? `filter-${field.field}`, raw) : null;
97
+ this.clauses.set([...this.clauses().filter((clause) => clause.field !== field.field), ...next ? [next] : []]);
98
+ }
99
+ remove(id) {
100
+ this.clauses.update((items) => items.filter((item) => item.id !== id));
101
+ }
102
+ update(next) {
103
+ this.clauses.update((items) => items.map((item) => item.id === next.id ? next : item));
104
+ }
105
+ static ɵfac = i0.ɵɵngDeclareFactory({
106
+ minVersion: "12.0.0",
107
+ version: "22.2.3",
108
+ ngImport: i0,
109
+ type: HyFilterBar,
110
+ deps: [],
111
+ target: i0.ɵɵFactoryTarget.Component
112
+ });
113
+ static ɵcmp = i0.ɵɵngDeclareComponent({
114
+ minVersion: "17.0.0",
115
+ version: "22.2.3",
116
+ type: HyFilterBar,
117
+ isStandalone: true,
118
+ selector: "hy-filter-bar",
119
+ inputs: {
120
+ fields: {
121
+ classPropertyName: "fields",
122
+ publicName: "fields",
123
+ isSignal: true,
124
+ isRequired: true,
125
+ transformFunction: null
126
+ },
127
+ clauses: {
128
+ classPropertyName: "clauses",
129
+ publicName: "clauses",
130
+ isSignal: true,
131
+ isRequired: false,
132
+ transformFunction: null
133
+ },
134
+ label: {
135
+ classPropertyName: "label",
136
+ publicName: "label",
137
+ isSignal: true,
138
+ isRequired: false,
139
+ transformFunction: null
140
+ },
141
+ clearLabel: {
142
+ classPropertyName: "clearLabel",
143
+ publicName: "clearLabel",
144
+ isSignal: true,
145
+ isRequired: false,
146
+ transformFunction: null
147
+ },
148
+ removeLabel: {
149
+ classPropertyName: "removeLabel",
150
+ publicName: "removeLabel",
151
+ isSignal: true,
152
+ isRequired: false,
153
+ transformFunction: null
154
+ },
155
+ anyLabel: {
156
+ classPropertyName: "anyLabel",
157
+ publicName: "anyLabel",
158
+ isSignal: true,
159
+ isRequired: false,
160
+ transformFunction: null
161
+ },
162
+ activeLabel: {
163
+ classPropertyName: "activeLabel",
164
+ publicName: "activeLabel",
165
+ isSignal: true,
166
+ isRequired: false,
167
+ transformFunction: null
168
+ }
169
+ },
170
+ outputs: { clauses: "clausesChange" },
171
+ ngImport: i0,
172
+ template: "<div class=\"editors\" role=\"group\" [attr.aria-label]=\"label()\">\n @for (field of fields(); track field.field) {\n <hy-field class=\"field\" [label]=\"field.label\">\n @if (field.options; as options) {\n <hy-select\n [options]=\"options\"\n [native]=\"true\"\n [value]=\"raw(field.field)\"\n (valueChange)=\"change(field, $event ?? '')\"\n [placeholder]=\"anyLabel()\"\n />\n } @else {\n <input\n hyInput\n type=\"search\"\n [attr.aria-label]=\"field.label\"\n [value]=\"raw(field.field)\"\n (input)=\"change(field, $any($event.target).value)\"\n />\n }\n </hy-field>\n }\n @if (clauses().length) {\n <button type=\"button\" (click)=\"clauses.set([])\">{{ clearLabel() }}</button>\n }\n <ng-content />\n</div>\n<div class=\"tokens\" role=\"list\" [attr.aria-label]=\"activeLabel()\">\n @for (item of view(); track item.clause.id) {\n <span role=\"listitem\">\n @if (item.editor; as editor) {\n <ng-container [ngTemplateOutlet]=\"editor\" [ngTemplateOutletContext]=\"item.context\" />\n } @else {\n <span>{{ item.label }}: {{ item.text }}</span>\n }\n <button\n type=\"button\"\n [attr.aria-label]=\"removeLabel() + ' ' + item.label\"\n (click)=\"remove(item.clause.id)\"\n >\n ×\n </button>\n </span>\n }\n</div>\n",
173
+ styles: [":host{display:block}.editors,.tokens{display:flex;flex-wrap:wrap;align-items:end;gap:.75rem}.tokens{margin-block-start:.75rem}.field{display:grid;gap:.25rem;font-size:.875rem;min-inline-size:min(12rem,100%);flex:1 1 12rem}button{min-block-size:44px;border:1px solid var(--hy-line);border-radius:var(--hy-radius-s);background:var(--hy-surface-1);color:var(--hy-ink);font:inherit;padding:.5rem .75rem}.tokens>span{display:inline-flex;align-items:center;gap:.5rem;background:var(--hy-surface-2);border-radius:var(--hy-radius-s);padding-inline-start:.75rem}button{cursor:pointer}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:2px}\n"],
174
+ dependencies: [
175
+ {
176
+ kind: "component",
177
+ type: HySelect,
178
+ selector: "hy-select",
179
+ inputs: [
180
+ "options",
181
+ "value",
182
+ "placeholder",
183
+ "name",
184
+ "optionTemplate",
185
+ "disabled",
186
+ "required",
187
+ "invalid",
188
+ "errors",
189
+ "touched",
190
+ "native"
191
+ ],
192
+ outputs: ["valueChange", "touch"]
193
+ },
194
+ {
195
+ kind: "directive",
196
+ type: NgTemplateOutlet,
197
+ selector: "[ngTemplateOutlet]",
198
+ inputs: [
199
+ "ngTemplateOutletContext",
200
+ "ngTemplateOutlet",
201
+ "ngTemplateOutletInjector"
202
+ ]
203
+ },
204
+ {
205
+ kind: "component",
206
+ type: HyField,
207
+ selector: "hy-field",
208
+ inputs: [
209
+ "label",
210
+ "hint",
211
+ "error",
212
+ "forceError",
213
+ "size"
214
+ ]
215
+ },
216
+ {
217
+ kind: "directive",
218
+ type: HyInput,
219
+ selector: "input[hyInput], textarea[hyInput]"
220
+ }
221
+ ],
222
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
223
+ });
224
+ };
225
+ i0.ɵɵngDeclareClassMetadata({
226
+ minVersion: "12.0.0",
227
+ version: "22.2.3",
228
+ ngImport: i0,
229
+ type: HyFilterBar,
230
+ decorators: [{
231
+ type: Component,
232
+ args: [{
233
+ selector: "hy-filter-bar",
234
+ imports: [
235
+ HySelect,
236
+ NgTemplateOutlet,
237
+ HyField,
238
+ HyInput
239
+ ],
240
+ changeDetection: ChangeDetectionStrategy.OnPush,
241
+ template: "<div class=\"editors\" role=\"group\" [attr.aria-label]=\"label()\">\n @for (field of fields(); track field.field) {\n <hy-field class=\"field\" [label]=\"field.label\">\n @if (field.options; as options) {\n <hy-select\n [options]=\"options\"\n [native]=\"true\"\n [value]=\"raw(field.field)\"\n (valueChange)=\"change(field, $event ?? '')\"\n [placeholder]=\"anyLabel()\"\n />\n } @else {\n <input\n hyInput\n type=\"search\"\n [attr.aria-label]=\"field.label\"\n [value]=\"raw(field.field)\"\n (input)=\"change(field, $any($event.target).value)\"\n />\n }\n </hy-field>\n }\n @if (clauses().length) {\n <button type=\"button\" (click)=\"clauses.set([])\">{{ clearLabel() }}</button>\n }\n <ng-content />\n</div>\n<div class=\"tokens\" role=\"list\" [attr.aria-label]=\"activeLabel()\">\n @for (item of view(); track item.clause.id) {\n <span role=\"listitem\">\n @if (item.editor; as editor) {\n <ng-container [ngTemplateOutlet]=\"editor\" [ngTemplateOutletContext]=\"item.context\" />\n } @else {\n <span>{{ item.label }}: {{ item.text }}</span>\n }\n <button\n type=\"button\"\n [attr.aria-label]=\"removeLabel() + ' ' + item.label\"\n (click)=\"remove(item.clause.id)\"\n >\n ×\n </button>\n </span>\n }\n</div>\n",
242
+ styles: [":host{display:block}.editors,.tokens{display:flex;flex-wrap:wrap;align-items:end;gap:.75rem}.tokens{margin-block-start:.75rem}.field{display:grid;gap:.25rem;font-size:.875rem;min-inline-size:min(12rem,100%);flex:1 1 12rem}button{min-block-size:44px;border:1px solid var(--hy-line);border-radius:var(--hy-radius-s);background:var(--hy-surface-1);color:var(--hy-ink);font:inherit;padding:.5rem .75rem}.tokens>span{display:inline-flex;align-items:center;gap:.5rem;background:var(--hy-surface-2);border-radius:var(--hy-radius-s);padding-inline-start:.75rem}button{cursor:pointer}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:2px}\n"]
243
+ }]
244
+ }],
245
+ propDecorators: {
246
+ fields: [{
247
+ type: i0.Input,
248
+ args: [{
249
+ isSignal: true,
250
+ alias: "fields",
251
+ required: true
252
+ }]
253
+ }],
254
+ clauses: [{
255
+ type: i0.Input,
256
+ args: [{
257
+ isSignal: true,
258
+ alias: "clauses",
259
+ required: false
260
+ }]
261
+ }, {
262
+ type: i0.Output,
263
+ args: ["clausesChange"]
264
+ }],
265
+ label: [{
266
+ type: i0.Input,
267
+ args: [{
268
+ isSignal: true,
269
+ alias: "label",
270
+ required: false
271
+ }]
272
+ }],
273
+ clearLabel: [{
274
+ type: i0.Input,
275
+ args: [{
276
+ isSignal: true,
277
+ alias: "clearLabel",
278
+ required: false
279
+ }]
280
+ }],
281
+ removeLabel: [{
282
+ type: i0.Input,
283
+ args: [{
284
+ isSignal: true,
285
+ alias: "removeLabel",
286
+ required: false
287
+ }]
288
+ }],
289
+ anyLabel: [{
290
+ type: i0.Input,
291
+ args: [{
292
+ isSignal: true,
293
+ alias: "anyLabel",
294
+ required: false
295
+ }]
296
+ }],
297
+ activeLabel: [{
298
+ type: i0.Input,
299
+ args: [{
300
+ isSignal: true,
301
+ alias: "activeLabel",
302
+ required: false
303
+ }]
304
+ }]
305
+ }
306
+ });
307
+ export { HyFilterBar, decodeFilters, encodeFilters, isFilterToken, resolveDateRange };
308
+
309
+ //# sourceMappingURL=hyalo-angular-filter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyalo-angular-filter.mjs","names":[],"sources":["../../../projects/hyalo/filter/state.ts","../../../projects/hyalo/filter/filter.ts","../../../projects/hyalo/filter/filter-bar.html"],"sourcesContent":["export type HyFilterScalar = string | number | boolean;\nexport type HyDatePreset = '24H' | '7D' | '30D' | '1Y';\nexport type HyDateRangeValue =\n | { readonly kind: 'preset'; readonly preset: HyDatePreset; readonly timeZone: string }\n | {\n readonly kind: 'absolute';\n readonly start: string;\n readonly end: string;\n readonly timeZone: string;\n };\nexport type HyFilterRule =\n | { readonly operator: 'eq'; readonly value: HyFilterScalar }\n | { readonly operator: 'in'; readonly value: readonly HyFilterScalar[] }\n | { readonly operator: 'contains'; readonly value: string }\n | { readonly operator: 'between'; readonly value: readonly [number, number] | HyDateRangeValue };\nexport type HyFilterClause<S> = {\n [K in keyof S]: { readonly id: string; readonly field: K } & S[K];\n}[keyof S];\nexport type HyFilterToken = { readonly id: string; readonly field: string } & HyFilterRule;\nexport interface HyFilterCodec<C extends HyFilterToken> {\n readonly accepts: (value: unknown) => value is C;\n}\nexport function encodeFilters<C extends HyFilterToken>(clauses: readonly C[]): string {\n return JSON.stringify({ version: 1, clauses });\n}\nexport function decodeFilters<C extends HyFilterToken>(\n text: string,\n codec: HyFilterCodec<C>,\n): readonly C[] {\n const payload: unknown = JSON.parse(text);\n if (\n !payload ||\n typeof payload !== 'object' ||\n !('version' in payload) ||\n payload.version !== 1 ||\n !('clauses' in payload) ||\n !Array.isArray(payload.clauses)\n )\n throw new Error('Unsupported filter state');\n const ids = new Set<string>();\n return payload.clauses.map((value: unknown) => {\n if (!isFilterToken(value) || !codec.accepts(value) || ids.has(value.id))\n throw new Error('Invalid or unsupported filter clause');\n ids.add(value.id);\n return value;\n });\n}\nexport function isFilterToken(value: unknown): value is HyFilterToken {\n if (\n !value ||\n typeof value !== 'object' ||\n !('id' in value) ||\n typeof value.id !== 'string' ||\n !value.id ||\n !('field' in value) ||\n typeof value.field !== 'string' ||\n !value.field ||\n !('operator' in value) ||\n !('value' in value)\n )\n return false;\n const data = value.value;\n const scalar = (v: unknown): v is HyFilterScalar =>\n typeof v === 'string' ||\n typeof v === 'boolean' ||\n (typeof v === 'number' && Number.isFinite(v));\n if (value.operator === 'eq') return scalar(data);\n if (value.operator === 'contains') return typeof data === 'string';\n if (value.operator === 'in') return Array.isArray(data) && data.every(scalar);\n if (value.operator !== 'between') return false;\n if (Array.isArray(data))\n return (\n data.length === 2 &&\n data.every((v) => typeof v === 'number' && Number.isFinite(v)) &&\n data[0] <= data[1]\n );\n if (\n !data ||\n typeof data !== 'object' ||\n !('timeZone' in data) ||\n typeof data.timeZone !== 'string' ||\n !('kind' in data)\n )\n return false;\n try {\n new Intl.DateTimeFormat('en', { timeZone: data.timeZone });\n } catch {\n return false;\n }\n if (data.kind === 'preset')\n return 'preset' in data && ['24H', '7D', '30D', '1Y'].includes(String(data.preset));\n const instant = (v: unknown): v is string =>\n typeof v === 'string' &&\n /^\\d{4}-\\d{2}-\\d{2}T.*(?:Z|[+-]\\d{2}:\\d{2})$/.test(v) &&\n Number.isFinite(Date.parse(v));\n return (\n data.kind === 'absolute' &&\n 'start' in data &&\n 'end' in data &&\n instant(data.start) &&\n instant(data.end) &&\n Date.parse(data.start) < Date.parse(data.end)\n );\n}\n\n/** Presets are rolling elapsed intervals; both editors use start-inclusive/end-exclusive instants. */\nexport function resolveDateRange(\n value: HyDateRangeValue,\n now: Date,\n): { readonly start: string; readonly end: string } {\n if (\n !isFilterToken({ id: 'range', field: 'time', operator: 'between', value }) ||\n !Number.isFinite(now.getTime())\n )\n throw new Error('Invalid date range');\n if (value.kind === 'absolute') return { start: value.start, end: value.end };\n const hours = { '24H': 24, '7D': 168, '30D': 720, '1Y': 8760 }[value.preset];\n return { start: new Date(now.getTime() - hours * 3600000).toISOString(), end: now.toISOString() };\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n TemplateRef,\n computed,\n input,\n model,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { HyField, HyInput } from '@hyalo/angular/field';\nimport { HySelect } from '@hyalo/angular/select';\nimport { type HySelectOption } from '@hyalo/angular/select';\nimport { type HyFilterToken } from './state';\nexport interface HyFilterEditorContext<C> {\n readonly $implicit: C;\n readonly update: (clause: C) => void;\n}\nexport interface HyFilterField<C extends HyFilterToken> {\n readonly field: C['field'];\n readonly label: string;\n readonly options?: readonly HySelectOption<string>[];\n readonly create: (id: string, value: string) => C | null;\n readonly editor?: TemplateRef<HyFilterEditorContext<C>>;\n readonly format?: (clause: C) => string;\n}\n@Component({\n selector: 'hy-filter-bar',\n imports: [HySelect, NgTemplateOutlet, HyField, HyInput],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './filter-bar.html',\n styleUrl: './filter-bar.css',\n})\nexport class HyFilterBar<C extends HyFilterToken> {\n readonly fields = input.required<readonly HyFilterField<C>[]>();\n readonly clauses = model<readonly C[]>([]);\n readonly label = input('Filter results');\n readonly clearLabel = input('Clear filters');\n readonly removeLabel = input('Remove');\n readonly anyLabel = input('Any');\n readonly activeLabel = input('Active filters');\n protected readonly view = computed(() =>\n this.clauses().map((clause) => {\n const field = this.fields().find((entry) => entry.field === clause.field);\n return {\n clause,\n label: field?.label ?? clause.field,\n text:\n field?.format?.(clause) ??\n (typeof clause.value === 'object' ? JSON.stringify(clause.value) : String(clause.value)),\n editor: field?.editor,\n context: { $implicit: clause, update: (next: C) => this.update(next) },\n };\n }),\n );\n protected raw(field: string): string {\n const value = this.clauses().find((clause) => clause.field === field)?.value;\n if (\n typeof value === 'object' &&\n value &&\n !Array.isArray(value) &&\n 'kind' in value &&\n value.kind === 'preset' &&\n 'preset' in value\n )\n return String(value.preset);\n return typeof value === 'string' ? value : '';\n }\n protected change(field: HyFilterField<C>, raw: string): void {\n const existing = this.clauses().find((clause) => clause.field === field.field);\n const next = raw ? field.create(existing?.id ?? `filter-${field.field}`, raw) : null;\n this.clauses.set([\n ...this.clauses().filter((clause) => clause.field !== field.field),\n ...(next ? [next] : []),\n ]);\n }\n protected remove(id: string): void {\n this.clauses.update((items) => items.filter((item) => item.id !== id));\n }\n private update(next: C): void {\n this.clauses.update((items) => items.map((item) => (item.id === next.id ? next : item)));\n }\n}\n","<div class=\"editors\" role=\"group\" [attr.aria-label]=\"label()\">\n @for (field of fields(); track field.field) {\n <hy-field class=\"field\" [label]=\"field.label\">\n @if (field.options; as options) {\n <hy-select\n [options]=\"options\"\n [native]=\"true\"\n [value]=\"raw(field.field)\"\n (valueChange)=\"change(field, $event ?? '')\"\n [placeholder]=\"anyLabel()\"\n />\n } @else {\n <input\n hyInput\n type=\"search\"\n [attr.aria-label]=\"field.label\"\n [value]=\"raw(field.field)\"\n (input)=\"change(field, $any($event.target).value)\"\n />\n }\n </hy-field>\n }\n @if (clauses().length) {\n <button type=\"button\" (click)=\"clauses.set([])\">{{ clearLabel() }}</button>\n }\n <ng-content />\n</div>\n<div class=\"tokens\" role=\"list\" [attr.aria-label]=\"activeLabel()\">\n @for (item of view(); track item.clause.id) {\n <span role=\"listitem\">\n @if (item.editor; as editor) {\n <ng-container [ngTemplateOutlet]=\"editor\" [ngTemplateOutletContext]=\"item.context\" />\n } @else {\n <span>{{ item.label }}: {{ item.text }}</span>\n }\n <button\n type=\"button\"\n [attr.aria-label]=\"removeLabel() + ' ' + item.label\"\n (click)=\"remove(item.clause.id)\"\n >\n ×\n </button>\n </span>\n }\n</div>\n"],"mappings":"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"}
@@ -0,0 +1,225 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, booleanAttribute, computed, inject, input, model, output } from "@angular/core";
3
+ import { HyMotion } from "@hyalo/angular/motion";
4
+ import { HyPopover } from "@hyalo/angular/popover";
5
+ var HyHotspot = class HyHotspot {
6
+ motion = inject(HyMotion);
7
+ label = input.required(...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
8
+ position = input.required(...ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []);
9
+ disabled = input(false, {
10
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
11
+ transform: booleanAttribute
12
+ });
13
+ description = input("", ...ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []);
14
+ mode = input("label", ...ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []);
15
+ open = model(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
16
+ placement = input("top", ...ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []);
17
+ closeLabel = input("Close details", ...ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []);
18
+ activated = output();
19
+ visible = computed(() => this.position().visible !== false && Number.isFinite(this.position().x) && Number.isFinite(this.position().y), ...ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []);
20
+ static ɵfac = i0.ɵɵngDeclareFactory({
21
+ minVersion: "12.0.0",
22
+ version: "22.2.3",
23
+ ngImport: i0,
24
+ type: HyHotspot,
25
+ deps: [],
26
+ target: i0.ɵɵFactoryTarget.Component
27
+ });
28
+ static ɵcmp = i0.ɵɵngDeclareComponent({
29
+ minVersion: "17.0.0",
30
+ version: "22.2.3",
31
+ type: HyHotspot,
32
+ isStandalone: true,
33
+ selector: "hy-hotspot",
34
+ inputs: {
35
+ label: {
36
+ classPropertyName: "label",
37
+ publicName: "label",
38
+ isSignal: true,
39
+ isRequired: true,
40
+ transformFunction: null
41
+ },
42
+ position: {
43
+ classPropertyName: "position",
44
+ publicName: "position",
45
+ isSignal: true,
46
+ isRequired: true,
47
+ transformFunction: null
48
+ },
49
+ disabled: {
50
+ classPropertyName: "disabled",
51
+ publicName: "disabled",
52
+ isSignal: true,
53
+ isRequired: false,
54
+ transformFunction: null
55
+ },
56
+ description: {
57
+ classPropertyName: "description",
58
+ publicName: "description",
59
+ isSignal: true,
60
+ isRequired: false,
61
+ transformFunction: null
62
+ },
63
+ mode: {
64
+ classPropertyName: "mode",
65
+ publicName: "mode",
66
+ isSignal: true,
67
+ isRequired: false,
68
+ transformFunction: null
69
+ },
70
+ open: {
71
+ classPropertyName: "open",
72
+ publicName: "open",
73
+ isSignal: true,
74
+ isRequired: false,
75
+ transformFunction: null
76
+ },
77
+ placement: {
78
+ classPropertyName: "placement",
79
+ publicName: "placement",
80
+ isSignal: true,
81
+ isRequired: false,
82
+ transformFunction: null
83
+ },
84
+ closeLabel: {
85
+ classPropertyName: "closeLabel",
86
+ publicName: "closeLabel",
87
+ isSignal: true,
88
+ isRequired: false,
89
+ transformFunction: null
90
+ }
91
+ },
92
+ outputs: {
93
+ open: "openChange",
94
+ activated: "activated"
95
+ },
96
+ host: { properties: {
97
+ "style.inset-inline-start.%": "position().x",
98
+ "style.inset-block-start.%": "position().y",
99
+ "hidden": "!visible()",
100
+ "attr.data-mode": "mode()",
101
+ "attr.data-open": "open()",
102
+ "attr.data-motion": "motion.enabled()",
103
+ "style.--hy-hotspot-duration": "motion.enabled() ? \"var(--hy-dur-quick)\" : \"0ms\""
104
+ } },
105
+ ngImport: i0,
106
+ template: "@if (description()) {\r\n <button\r\n #popover=\"hyPopover\"\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n [hyPopover]=\"details\"\r\n [popoverLabel]=\"label()\"\r\n popoverMaterial=\"solid\"\r\n [popoverPlacement]=\"placement()\"\r\n [(popoverOpen)]=\"open\"\r\n (click)=\"activated.emit()\"\r\n >\r\n <span class=\"dot\" aria-hidden=\"true\"></span><span class=\"label\">{{ label() }}</span>\r\n </button>\r\n <ng-template #details>\r\n <div class=\"details\">\r\n <strong>{{ label() }}</strong>\r\n <p>{{ description() }}</p>\r\n <button class=\"close\" type=\"button\" (click)=\"popover.close()\">{{ closeLabel() }}</button>\r\n </div>\r\n </ng-template>\r\n} @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (click)=\"activated.emit()\"\r\n >\r\n <span class=\"dot\" aria-hidden=\"true\"></span><span class=\"label\">{{ label() }}</span>\r\n </button>\r\n}\r\n",
107
+ styles: [":host{display:block;position:absolute;z-index:1;transform:translate(-50%,-50%)}:host([hidden]){display:none}button{display:flex;align-items:center;gap:var(--hy-space-2);min-block-size:2.75rem;padding:var(--hy-space-2) var(--hy-space-4);border:1px solid var(--hy-line-strong);border-radius:var(--hy-radius-pill);color:var(--hy-ink);background:var(--hy-surface-1);box-shadow:var(--hy-glass-shadow);font:inherit;cursor:pointer;transition:transform var(--hy-hotspot-duration) var(--hy-ease-out),border-color var(--hy-hotspot-duration) ease}button[aria-expanded=true]{border-color:var(--hy-primary)}:host([data-motion=\"true\"]) button:active:not(:disabled){transform:scale(.97)}@media(hover:hover)and (pointer:fine){:host([data-motion=\"true\"]) button:hover:not(:disabled){transform:translateY(-2px)}}:host([data-mode=\"pin\"]) button{inline-size:2.75rem;padding:0;justify-content:center}:host([data-mode=\"pin\"]) .label{position:absolute;inline-size:1px;block-size:1px;overflow:hidden;clip-path:inset(50%)}strong{display:block;color:var(--hy-ink)}.details{display:block;min-inline-size:12rem;max-inline-size:18rem}p{max-inline-size:28ch;margin-block:var(--hy-space-2) var(--hy-space-4);color:var(--hy-ink-2);line-height:var(--hy-leading)}.close{min-block-size:2rem;padding:var(--hy-space-1) var(--hy-space-3);border-radius:var(--hy-radius-s);box-shadow:none;background:var(--hy-primary-wash);color:var(--hy-primary)}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:4px}button:disabled{opacity:.6;cursor:default}.dot{inline-size:.5rem;block-size:.5rem;border-radius:50%;background:var(--hy-primary)}:host:dir(rtl){transform:translate(50%,-50%)}\n"],
108
+ dependencies: [{
109
+ kind: "directive",
110
+ type: HyPopover,
111
+ selector: "[hyPopover]",
112
+ inputs: [
113
+ "hyPopover",
114
+ "popoverLabel",
115
+ "popoverMaterial",
116
+ "popoverPlacement",
117
+ "popoverOpen"
118
+ ],
119
+ outputs: ["popoverOpenChange"],
120
+ exportAs: ["hyPopover"]
121
+ }],
122
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
123
+ });
124
+ };
125
+ i0.ɵɵngDeclareClassMetadata({
126
+ minVersion: "12.0.0",
127
+ version: "22.2.3",
128
+ ngImport: i0,
129
+ type: HyHotspot,
130
+ decorators: [{
131
+ type: Component,
132
+ args: [{
133
+ selector: "hy-hotspot",
134
+ imports: [HyPopover],
135
+ changeDetection: ChangeDetectionStrategy.OnPush,
136
+ host: {
137
+ "[style.inset-inline-start.%]": "position().x",
138
+ "[style.inset-block-start.%]": "position().y",
139
+ "[hidden]": "!visible()",
140
+ "[attr.data-mode]": "mode()",
141
+ "[attr.data-open]": "open()",
142
+ "[attr.data-motion]": "motion.enabled()",
143
+ "[style.--hy-hotspot-duration]": "motion.enabled() ? \"var(--hy-dur-quick)\" : \"0ms\""
144
+ },
145
+ template: "@if (description()) {\r\n <button\r\n #popover=\"hyPopover\"\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n [hyPopover]=\"details\"\r\n [popoverLabel]=\"label()\"\r\n popoverMaterial=\"solid\"\r\n [popoverPlacement]=\"placement()\"\r\n [(popoverOpen)]=\"open\"\r\n (click)=\"activated.emit()\"\r\n >\r\n <span class=\"dot\" aria-hidden=\"true\"></span><span class=\"label\">{{ label() }}</span>\r\n </button>\r\n <ng-template #details>\r\n <div class=\"details\">\r\n <strong>{{ label() }}</strong>\r\n <p>{{ description() }}</p>\r\n <button class=\"close\" type=\"button\" (click)=\"popover.close()\">{{ closeLabel() }}</button>\r\n </div>\r\n </ng-template>\r\n} @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (click)=\"activated.emit()\"\r\n >\r\n <span class=\"dot\" aria-hidden=\"true\"></span><span class=\"label\">{{ label() }}</span>\r\n </button>\r\n}\r\n",
146
+ styles: [":host{display:block;position:absolute;z-index:1;transform:translate(-50%,-50%)}:host([hidden]){display:none}button{display:flex;align-items:center;gap:var(--hy-space-2);min-block-size:2.75rem;padding:var(--hy-space-2) var(--hy-space-4);border:1px solid var(--hy-line-strong);border-radius:var(--hy-radius-pill);color:var(--hy-ink);background:var(--hy-surface-1);box-shadow:var(--hy-glass-shadow);font:inherit;cursor:pointer;transition:transform var(--hy-hotspot-duration) var(--hy-ease-out),border-color var(--hy-hotspot-duration) ease}button[aria-expanded=true]{border-color:var(--hy-primary)}:host([data-motion=\"true\"]) button:active:not(:disabled){transform:scale(.97)}@media(hover:hover)and (pointer:fine){:host([data-motion=\"true\"]) button:hover:not(:disabled){transform:translateY(-2px)}}:host([data-mode=\"pin\"]) button{inline-size:2.75rem;padding:0;justify-content:center}:host([data-mode=\"pin\"]) .label{position:absolute;inline-size:1px;block-size:1px;overflow:hidden;clip-path:inset(50%)}strong{display:block;color:var(--hy-ink)}.details{display:block;min-inline-size:12rem;max-inline-size:18rem}p{max-inline-size:28ch;margin-block:var(--hy-space-2) var(--hy-space-4);color:var(--hy-ink-2);line-height:var(--hy-leading)}.close{min-block-size:2rem;padding:var(--hy-space-1) var(--hy-space-3);border-radius:var(--hy-radius-s);box-shadow:none;background:var(--hy-primary-wash);color:var(--hy-primary)}button:focus-visible{outline:2px solid var(--hy-primary);outline-offset:4px}button:disabled{opacity:.6;cursor:default}.dot{inline-size:.5rem;block-size:.5rem;border-radius:50%;background:var(--hy-primary)}:host:dir(rtl){transform:translate(50%,-50%)}\n"]
147
+ }]
148
+ }],
149
+ propDecorators: {
150
+ label: [{
151
+ type: i0.Input,
152
+ args: [{
153
+ isSignal: true,
154
+ alias: "label",
155
+ required: true
156
+ }]
157
+ }],
158
+ position: [{
159
+ type: i0.Input,
160
+ args: [{
161
+ isSignal: true,
162
+ alias: "position",
163
+ required: true
164
+ }]
165
+ }],
166
+ disabled: [{
167
+ type: i0.Input,
168
+ args: [{
169
+ isSignal: true,
170
+ alias: "disabled",
171
+ required: false
172
+ }]
173
+ }],
174
+ description: [{
175
+ type: i0.Input,
176
+ args: [{
177
+ isSignal: true,
178
+ alias: "description",
179
+ required: false
180
+ }]
181
+ }],
182
+ mode: [{
183
+ type: i0.Input,
184
+ args: [{
185
+ isSignal: true,
186
+ alias: "mode",
187
+ required: false
188
+ }]
189
+ }],
190
+ open: [{
191
+ type: i0.Input,
192
+ args: [{
193
+ isSignal: true,
194
+ alias: "open",
195
+ required: false
196
+ }]
197
+ }, {
198
+ type: i0.Output,
199
+ args: ["openChange"]
200
+ }],
201
+ placement: [{
202
+ type: i0.Input,
203
+ args: [{
204
+ isSignal: true,
205
+ alias: "placement",
206
+ required: false
207
+ }]
208
+ }],
209
+ closeLabel: [{
210
+ type: i0.Input,
211
+ args: [{
212
+ isSignal: true,
213
+ alias: "closeLabel",
214
+ required: false
215
+ }]
216
+ }],
217
+ activated: [{
218
+ type: i0.Output,
219
+ args: ["activated"]
220
+ }]
221
+ }
222
+ });
223
+ export { HyHotspot };
224
+
225
+ //# sourceMappingURL=hyalo-angular-hotspot.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyalo-angular-hotspot.mjs","names":[],"sources":["../../../projects/hyalo/hotspot/hotspot.ts","../../../projects/hyalo/hotspot/hotspot.html"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n booleanAttribute,\r\n computed,\r\n input,\r\n inject,\r\n model,\r\n output,\r\n} from '@angular/core';\r\nimport { HyMotion } from '@hyalo/angular/motion';\r\nimport { HyPopover } from '@hyalo/angular/popover';\r\nimport type { HyPlacement } from '@hyalo/angular/overlay';\r\nexport type HyHotspotMode = 'label' | 'pin';\r\nexport interface HyHotspotPosition {\r\n readonly x: number;\r\n readonly y: number;\r\n readonly visible?: boolean;\r\n}\r\n/** Pass screen coordinates from your scene's projection. Position is relative to its frame. */\r\n@Component({\r\n selector: 'hy-hotspot',\r\n imports: [HyPopover],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n '[style.inset-inline-start.%]': 'position().x',\r\n '[style.inset-block-start.%]': 'position().y',\r\n '[hidden]': '!visible()',\r\n '[attr.data-mode]': 'mode()',\r\n '[attr.data-open]': 'open()',\r\n '[attr.data-motion]': 'motion.enabled()',\r\n '[style.--hy-hotspot-duration]': 'motion.enabled() ? \"var(--hy-dur-quick)\" : \"0ms\"',\r\n },\r\n templateUrl: './hotspot.html',\r\n styleUrl: './hotspot.css',\r\n})\r\nexport class HyHotspot {\r\n protected readonly motion = inject(HyMotion);\r\n readonly label = input.required<string>();\r\n readonly position = input.required<HyHotspotPosition>();\r\n readonly disabled = input(false, { transform: booleanAttribute });\r\n /** Optional detail panel. Without a description this stays a plain action button. */\r\n readonly description = input('');\r\n readonly mode = input<HyHotspotMode>('label');\r\n readonly open = model(false);\r\n readonly placement = input<HyPlacement>('top');\r\n readonly closeLabel = input('Close details');\r\n readonly activated = output<void>();\r\n protected readonly visible = computed(\r\n () =>\r\n this.position().visible !== false &&\r\n Number.isFinite(this.position().x) &&\r\n Number.isFinite(this.position().y),\r\n );\r\n}\r\n","@if (description()) {\r\n <button\r\n #popover=\"hyPopover\"\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n [hyPopover]=\"details\"\r\n [popoverLabel]=\"label()\"\r\n popoverMaterial=\"solid\"\r\n [popoverPlacement]=\"placement()\"\r\n [(popoverOpen)]=\"open\"\r\n (click)=\"activated.emit()\"\r\n >\r\n <span class=\"dot\" aria-hidden=\"true\"></span><span class=\"label\">{{ label() }}</span>\r\n </button>\r\n <ng-template #details>\r\n <div class=\"details\">\r\n <strong>{{ label() }}</strong>\r\n <p>{{ description() }}</p>\r\n <button class=\"close\" type=\"button\" (click)=\"popover.close()\">{{ closeLabel() }}</button>\r\n </div>\r\n </ng-template>\r\n} @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (click)=\"activated.emit()\"\r\n >\r\n <span class=\"dot\" aria-hidden=\"true\"></span><span class=\"label\">{{ label() }}</span>\r\n </button>\r\n}\r\n"],"mappings":"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"}