ngwr 14.7.0 → 14.8.0

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 (152) hide show
  1. package/bar-chart/styles/_index.scss +1 -0
  2. package/calendar-heatmap/styles/_index.scss +1 -0
  3. package/cascader/styles/_rules.scss +86 -14
  4. package/date-picker/styles/_index.scss +30 -0
  5. package/density/styles/_index.scss +4 -2
  6. package/donut-chart/styles/_index.scss +10 -0
  7. package/dropdown/styles/_index.scss +67 -5
  8. package/event-calendar/styles/_index.scss +209 -35
  9. package/fesm2022/ngwr-bar-chart.mjs +29 -4
  10. package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
  11. package/fesm2022/ngwr-calendar-heatmap.mjs +59 -4
  12. package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
  13. package/fesm2022/ngwr-cascader.mjs +2 -2
  14. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  15. package/fesm2022/ngwr-checkbox.mjs +12 -2
  16. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  17. package/fesm2022/ngwr-date-picker.mjs +705 -46
  18. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  19. package/fesm2022/ngwr-donut-chart.mjs +46 -4
  20. package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
  21. package/fesm2022/ngwr-dropdown.mjs +166 -17
  22. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  23. package/fesm2022/ngwr-event-calendar.mjs +9 -2
  24. package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
  25. package/fesm2022/ngwr-form.mjs +52 -1
  26. package/fesm2022/ngwr-form.mjs.map +1 -1
  27. package/fesm2022/ngwr-gauge.mjs +33 -4
  28. package/fesm2022/ngwr-gauge.mjs.map +1 -1
  29. package/fesm2022/ngwr-i18n-ar.mjs +2 -0
  30. package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
  31. package/fesm2022/ngwr-i18n-cs.mjs +2 -0
  32. package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
  33. package/fesm2022/ngwr-i18n-de.mjs +2 -0
  34. package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
  35. package/fesm2022/ngwr-i18n-en.mjs +5 -0
  36. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  37. package/fesm2022/ngwr-i18n-es.mjs +2 -0
  38. package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
  39. package/fesm2022/ngwr-i18n-fr.mjs +2 -0
  40. package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
  41. package/fesm2022/ngwr-i18n-he.mjs +2 -0
  42. package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
  43. package/fesm2022/ngwr-i18n-hi.mjs +2 -0
  44. package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
  45. package/fesm2022/ngwr-i18n-id.mjs +2 -0
  46. package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
  47. package/fesm2022/ngwr-i18n-it.mjs +2 -0
  48. package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
  49. package/fesm2022/ngwr-i18n-ja.mjs +2 -0
  50. package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
  51. package/fesm2022/ngwr-i18n-ko.mjs +2 -0
  52. package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
  53. package/fesm2022/ngwr-i18n-nl.mjs +2 -0
  54. package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
  55. package/fesm2022/ngwr-i18n-pl.mjs +2 -0
  56. package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
  57. package/fesm2022/ngwr-i18n-pt.mjs +2 -0
  58. package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
  59. package/fesm2022/ngwr-i18n-ru.mjs +2 -0
  60. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  61. package/fesm2022/ngwr-i18n-sv.mjs +2 -0
  62. package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
  63. package/fesm2022/ngwr-i18n-tr.mjs +2 -0
  64. package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
  65. package/fesm2022/ngwr-i18n-uk.mjs +2 -0
  66. package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
  67. package/fesm2022/ngwr-i18n-vi.mjs +2 -0
  68. package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
  69. package/fesm2022/ngwr-i18n-zh-TW.mjs +2 -0
  70. package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
  71. package/fesm2022/ngwr-i18n-zh.mjs +2 -0
  72. package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
  73. package/fesm2022/ngwr-input-number.mjs +12 -0
  74. package/fesm2022/ngwr-input-number.mjs.map +1 -1
  75. package/fesm2022/ngwr-line-chart.mjs +16 -5
  76. package/fesm2022/ngwr-line-chart.mjs.map +1 -1
  77. package/fesm2022/ngwr-meter-group-testing.mjs +7 -3
  78. package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -1
  79. package/fesm2022/ngwr-meter-group.mjs +24 -4
  80. package/fesm2022/ngwr-meter-group.mjs.map +1 -1
  81. package/fesm2022/ngwr-page-header.mjs +10 -2
  82. package/fesm2022/ngwr-page-header.mjs.map +1 -1
  83. package/fesm2022/ngwr-popover.mjs +569 -7
  84. package/fesm2022/ngwr-popover.mjs.map +1 -1
  85. package/fesm2022/ngwr-sidebar.mjs +7 -0
  86. package/fesm2022/ngwr-sidebar.mjs.map +1 -1
  87. package/fesm2022/ngwr-sparkline.mjs +82 -8
  88. package/fesm2022/ngwr-sparkline.mjs.map +1 -1
  89. package/fesm2022/ngwr-table.mjs +1 -1
  90. package/fesm2022/ngwr-table.mjs.map +1 -1
  91. package/fesm2022/ngwr-toolbar.mjs +7 -0
  92. package/fesm2022/ngwr-toolbar.mjs.map +1 -1
  93. package/fesm2022/ngwr-version.mjs +1 -1
  94. package/fesm2022/ngwr-version.mjs.map +1 -1
  95. package/form/styles/_index.scss +11 -1
  96. package/gauge/styles/_index.scss +1 -0
  97. package/i18n/ar.json +3 -1
  98. package/i18n/cs.json +3 -1
  99. package/i18n/de.json +3 -1
  100. package/i18n/en.json +3 -1
  101. package/i18n/es.json +3 -1
  102. package/i18n/fr.json +3 -1
  103. package/i18n/he.json +3 -1
  104. package/i18n/hi.json +3 -1
  105. package/i18n/id.json +3 -1
  106. package/i18n/it.json +3 -1
  107. package/i18n/ja.json +3 -1
  108. package/i18n/ko.json +3 -1
  109. package/i18n/nl.json +3 -1
  110. package/i18n/pl.json +3 -1
  111. package/i18n/pt.json +3 -1
  112. package/i18n/ru.json +3 -1
  113. package/i18n/sv.json +3 -1
  114. package/i18n/tr.json +3 -1
  115. package/i18n/uk.json +3 -1
  116. package/i18n/vi.json +3 -1
  117. package/i18n/zh-TW.json +3 -1
  118. package/i18n/zh.json +3 -1
  119. package/input/styles/_index.scss +19 -0
  120. package/input-number/styles/_index.scss +69 -0
  121. package/line-chart/styles/_index.scss +30 -2
  122. package/llms-full.txt +3 -3
  123. package/meter-group/styles/_index.scss +1 -0
  124. package/overlay/styles/_arrow.scss +27 -2
  125. package/package.json +1 -1
  126. package/page-header/styles/_index.scss +37 -1
  127. package/pagination/styles/_index.scss +9 -5
  128. package/popover/styles/_index.scss +73 -5
  129. package/select/styles/_index.scss +48 -9
  130. package/sidebar/styles/_index.scss +34 -2
  131. package/sparkline/styles/_index.scss +19 -0
  132. package/toolbar/styles/_index.scss +35 -1
  133. package/tree/styles/_index.scss +45 -6
  134. package/types/ngwr-bar-chart.d.ts +19 -1
  135. package/types/ngwr-calendar-heatmap.d.ts +29 -1
  136. package/types/ngwr-checkbox.d.ts +2 -0
  137. package/types/ngwr-date-picker.d.ts +308 -43
  138. package/types/ngwr-donut-chart.d.ts +24 -1
  139. package/types/ngwr-dropdown.d.ts +22 -2
  140. package/types/ngwr-event-calendar.d.ts +8 -0
  141. package/types/ngwr-form.d.ts +35 -5
  142. package/types/ngwr-gauge.d.ts +20 -1
  143. package/types/ngwr-input-number.d.ts +7 -0
  144. package/types/ngwr-line-chart.d.ts +9 -1
  145. package/types/ngwr-meter-group-testing.d.ts +3 -2
  146. package/types/ngwr-meter-group.d.ts +14 -1
  147. package/types/ngwr-page-header.d.ts +10 -2
  148. package/types/ngwr-popover.d.ts +154 -3
  149. package/types/ngwr-sidebar.d.ts +7 -0
  150. package/types/ngwr-sparkline.d.ts +43 -1
  151. package/types/ngwr-toolbar.d.ts +7 -0
  152. package/types/ngwr-version.d.ts +1 -1
@@ -8,15 +8,19 @@
8
8
  /// one of the 120-odd style entries that referenced tokens without pulling the
9
9
  /// layer that declares them: `@use 'ngwr/event-calendar'` on its own emitted
10
10
  /// 5.5 kB of rules carrying 57 unresolved `var(--wr-*)` references, so the grid
11
- /// lines (`box-shadow`, hence no fallback) vanished and the text fell back to
12
- /// black. The ten other entries that skip the load — `affix`, `density` and the
13
- /// eight canvas / text-animation ones — reference no token at all, which is why
14
- /// a sweep for "who is missing it" is not enough on its own.
11
+ /// lines (then a `box-shadow`, hence no fallback) vanished and the text fell
12
+ /// back to black. The ten other entries that skip the load — `affix`, `density`
13
+ /// and the eight canvas / text-animation ones — reference no token at all, which
14
+ /// is why a sweep for "who is missing it" is not enough on its own.
15
15
  ///
16
- /// Grid lines are `box-shadow: inset`, never borders. A border would take up
17
- /// layout space, and the whole chip model depends on cell boxes being exactly
18
- /// contiguous: a band's `calc(var(--span) * 100%)` is only the right width if
19
- /// one cell ends precisely where the next begins.
16
+ /// Grid lines are borders on an absolutely positioned `::after`, never on the
17
+ /// cell itself. A border on the cell would take up layout space, and the whole
18
+ /// chip model depends on cell boxes being exactly contiguous: a band's
19
+ /// `calc(var(--span) * 100%)` is only the right width if one cell ends precisely
20
+ /// where the next begins. They used to be `box-shadow: inset`, which costs no
21
+ /// space either but has no logical form — and each cell drew its line on the
22
+ /// physical right and bottom whether or not that edge was the frame, so the last
23
+ /// column and the last row painted a second hairline against the grid's own.
20
24
  @use '../../theme/styles';
21
25
 
22
26
  .wr-event-calendar {
@@ -29,6 +33,17 @@
29
33
  // dark enough that `--wr-color-on-surface-muted` on top of it lands at 3.6:1.
30
34
  --wr-event-calendar-fill: var(--wr-color-fill);
31
35
  --wr-event-calendar-cols: 7;
36
+ // A chip is a 20px strip carrying a 3px accent on its leading edge, and the
37
+ // library's small radius (6px) bent that accent into a bracket. Half of it
38
+ // keeps the corner soft and the accent straight, and still follows a theme
39
+ // that re-tunes `--wr-border-radius-sm`.
40
+ --wr-event-calendar-chip-radius: calc(var(--wr-border-radius-sm) / 2);
41
+ // Space above the first chip (below the day number, or below the header rule
42
+ // in the all-day band) and between stacked chips.
43
+ --wr-event-calendar-chip-gap: 0.25rem;
44
+ // How far a chip stands in from the lines of the cell it sits in — on both
45
+ // inline sides, and below a timed chip so back-to-back events do not merge.
46
+ --wr-event-calendar-chip-inset: 0.125rem;
32
47
 
33
48
  display: flex;
34
49
  flex-direction: column;
@@ -75,6 +90,9 @@
75
90
  display: grid;
76
91
  overflow: hidden;
77
92
  border-radius: var(--wr-border-radius-base);
93
+ // The frame, spread OUTSIDE the box. It owns the four outer edges, which is
94
+ // why no cell draws a line on a side that meets it (see the grid lines
95
+ // below).
78
96
  box-shadow: 0 0 0 1px var(--wr-event-calendar-line);
79
97
 
80
98
  &--month {
@@ -82,7 +100,15 @@
82
100
  }
83
101
 
84
102
  &--time {
85
- grid-template-columns: var(--wr-event-calendar-gutter) repeat(var(--wr-event-calendar-cols), minmax(0, 1fr));
103
+ // The hook is the gutter's FLOOR, not its width. A fixed 3.75rem could not
104
+ // hold "09:00 AM" at the label's own padding, so the label wrapped onto a
105
+ // second line, the rows carrying one grew to 36px while the slot cells
106
+ // stayed 24px, and every column line broke for 12px at every hour — and a
107
+ // timed chip, sized in percentages of one 24px slot, ended short of its
108
+ // own end time by 12px per hour it crossed.
109
+ grid-template-columns:
110
+ minmax(var(--wr-event-calendar-gutter), max-content)
111
+ repeat(var(--wr-event-calendar-cols), minmax(0, 1fr));
86
112
  }
87
113
  }
88
114
 
@@ -94,13 +120,13 @@
94
120
 
95
121
  &__weekday,
96
122
  &__colhead {
123
+ position: relative;
97
124
  padding: 0.5rem 0.375rem;
98
125
  font-size: var(--wr-text-xs);
99
126
  font-weight: var(--wr-font-weight-medium);
100
127
  color: var(--wr-color-on-surface-muted);
101
128
  text-align: center;
102
129
  background: var(--wr-event-calendar-fill);
103
- box-shadow: inset 0 -1px 0 var(--wr-event-calendar-line);
104
130
  }
105
131
 
106
132
  &__colhead {
@@ -122,11 +148,36 @@
122
148
  &__gutter {
123
149
  padding: 0 0.5rem;
124
150
  font-size: var(--wr-text-xs);
151
+ // One line box exactly one em tall, so the nudge below centres the label on
152
+ // its line and the label can never make a slot row taller than the slot.
153
+ line-height: 1;
125
154
  color: var(--wr-color-on-surface-muted);
126
155
  text-align: end;
156
+ white-space: nowrap;
127
157
  // Nudged up so the label reads as the line it labels, not the band below it.
158
+ // The transform moves the box, so the gutter draws no line of its own — the
159
+ // divider is the first day column's (see the grid lines below).
128
160
  transform: translateY(-0.5em);
129
- box-shadow: inset -1px 0 0 var(--wr-event-calendar-line);
161
+ }
162
+
163
+ // The all-day label names a band, not a line: its top level with the first
164
+ // chip's. Not centred on the chip — the first hour's label below is centred on
165
+ // the band's bottom rule, and a centred "All day" ran into it.
166
+ //
167
+ // And it does not size the column. The hour labels have to stay on one line,
168
+ // because a wrapped one grows its row; this label only grows the all-day row,
169
+ // which is a floor anyway. Left to `nowrap`, "Toute la journée" widened the
170
+ // French gutter from 72px to 107px and took a fifth off every day column at
171
+ // phone width, and the English label overrode a smaller gutter hook. A wrapped
172
+ // label grows the row through its bottom padding instead: the first hour's
173
+ // label is lifted 0.5em into this row, and the other 0.5em is the space a
174
+ // one-line "All day" already leaves above it. Without it the second line of
175
+ // "Toute la journée" overlapped "08:00 AM".
176
+ &__row--allday > &__gutter {
177
+ contain: inline-size;
178
+ padding-block: var(--wr-event-calendar-chip-gap) 1em;
179
+ white-space: normal;
180
+ transform: none;
130
181
  }
131
182
 
132
183
  &__cell {
@@ -137,7 +188,6 @@
137
188
  position: relative;
138
189
  min-width: 0;
139
190
  cursor: pointer;
140
- box-shadow: inset -1px -1px 0 var(--wr-event-calendar-line);
141
191
 
142
192
  &:focus-visible {
143
193
  z-index: 2;
@@ -146,7 +196,18 @@
146
196
  }
147
197
 
148
198
  &--day {
149
- min-height: 5.5rem;
199
+ // A floor that knows the lanes. Every chip is absolutely positioned, so
200
+ // nothing in flow made the cell tall enough for its last lane: a third
201
+ // chip hung into the next week's row. `--wr-event-calendar-lanes` is the
202
+ // number of lanes the week row fills, set on the row and inherited through
203
+ // its `display: contents`.
204
+ min-height: max(
205
+ 5.5rem,
206
+ calc(
207
+ 1.75rem + var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lanes, 0) *
208
+ (var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
209
+ )
210
+ );
150
211
  padding: 0.25rem;
151
212
  }
152
213
 
@@ -164,22 +225,92 @@
164
225
  }
165
226
 
166
227
  &--allday {
167
- min-height: calc(var(--wr-event-calendar-band-height) + 0.5rem);
168
- padding: 0.125rem 0;
228
+ // Same rule as a day cell: the band has no ceiling on lanes, and a second
229
+ // all-day event used to spill over the first hour of the grid.
230
+ min-height: calc(
231
+ var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lanes, 1) *
232
+ (var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
233
+ );
169
234
  }
170
235
 
171
236
  &--slot {
172
- height: var(--wr-event-calendar-slot-height);
173
- box-shadow: inset -1px 0 0 var(--wr-event-calendar-line);
237
+ // A floor rather than a height, so a row that grows anyway stretches its
238
+ // cells with it instead of leaving their lines short.
239
+ min-height: var(--wr-event-calendar-slot-height);
174
240
  }
241
+ }
175
242
 
176
- &--major {
177
- box-shadow:
178
- inset -1px 0 0 var(--wr-event-calendar-line),
179
- inset 0 1px 0 var(--wr-event-calendar-line);
243
+ // ------------------------------------------------------------- grid lines
244
+ //
245
+ // One hairline per edge, and one owner per line. A cell draws the line on its
246
+ // inline END and its block END, and draws nothing where that edge is the
247
+ // frame; the time grid draws hour lines on the block START of a major row,
248
+ // except where a header or the all-day band already put a rule there. Logical
249
+ // sides throughout, so the lines follow the columns under `dir="rtl"`.
250
+ &__weekday,
251
+ &__colhead,
252
+ &__cell {
253
+ &::after {
254
+ position: absolute;
255
+ inset: 0;
256
+ pointer-events: none;
257
+ content: '';
258
+ border: 0 solid var(--wr-event-calendar-line);
180
259
  }
181
260
  }
182
261
 
262
+ &__weekday::after,
263
+ &__colhead::after {
264
+ border-block-end-width: 1px;
265
+ }
266
+
267
+ &__cell--day::after,
268
+ &__cell--allday::after {
269
+ border-inline-end-width: 1px;
270
+ border-block-end-width: 1px;
271
+ }
272
+
273
+ &__cell--slot::after {
274
+ border-inline-end-width: 1px;
275
+ }
276
+
277
+ &__cell--major::after {
278
+ border-block-start-width: 1px;
279
+ }
280
+
281
+ // The divider between the gutter and the days. The first day column draws it,
282
+ // in every row, because the gutter's labels are moved with a transform that
283
+ // would carry any line of the gutter's own up with them — it used to stop
284
+ // 0.5em short of the grid's bottom edge.
285
+ &__gutter + &__colhead::after,
286
+ &__gutter + &__cell::after {
287
+ border-inline-start-width: 1px;
288
+ }
289
+
290
+ // The first slot row sits directly under the header rule or the all-day rule.
291
+ &__row:first-child + &__row > &__cell--major::after,
292
+ &__row--allday + &__row > &__cell--major::after {
293
+ border-block-start-width: 0;
294
+ }
295
+
296
+ // Edges that meet the frame.
297
+ &__row > :last-child::after {
298
+ border-inline-end-width: 0;
299
+ }
300
+
301
+ &__row:last-child > &__cell::after {
302
+ border-block-end-width: 0;
303
+ }
304
+
305
+ // Under the focus ring, never over it. A focused cell takes `z-index: 2`, so
306
+ // it is a stacking context, and Chromium paints a positioned `::after` inside
307
+ // one AFTER the cell's own outline: the inset ring lost its outer pixel on
308
+ // every side the cell draws a line on. A negative z-index still paints above
309
+ // the cell's background, so a muted day keeps its lines.
310
+ &__cell:focus-visible::after {
311
+ z-index: -1;
312
+ }
313
+
183
314
  &__daynum {
184
315
  display: inline-flex;
185
316
  align-items: center;
@@ -207,7 +338,7 @@
207
338
  background: color-mix(in srgb, var(--wr-event-calendar-color) 18%, transparent);
208
339
  border: 0;
209
340
  border-inline-start: 3px solid var(--wr-event-calendar-color);
210
- border-radius: var(--wr-border-radius-sm);
341
+ border-radius: var(--wr-event-calendar-chip-radius);
211
342
  transition: filter var(--wr-transition-short);
212
343
 
213
344
  &:hover {
@@ -221,19 +352,31 @@
221
352
  }
222
353
 
223
354
  &--band {
224
- inset-inline-start: 0.125rem;
355
+ inset-inline-start: var(--wr-event-calendar-chip-inset);
356
+ // `offset` is where the chips start — below the day number in a month
357
+ // cell, at the top of the all-day band — and the first lane keeps one gap
358
+ // clear of it, the way every later lane keeps one clear of the chip above.
225
359
  top: calc(
226
- var(--wr-event-calendar-offset) + var(--wr-event-calendar-lane) *
227
- (var(--wr-event-calendar-band-height) + 0.125rem)
360
+ var(--wr-event-calendar-offset) + var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lane) *
361
+ (var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
228
362
  );
229
363
  // Reaching across `--span` cells: each is exactly 100% of this one,
230
364
  // because the grid has no gaps and the lines cost no layout space.
231
- width: calc(var(--wr-event-calendar-span) * 100% - 0.25rem);
365
+ width: calc(var(--wr-event-calendar-span) * 100% - 2 * var(--wr-event-calendar-chip-inset));
232
366
  height: var(--wr-event-calendar-band-height);
233
367
  padding: 0 0.375rem;
234
368
  }
235
369
 
236
370
  &--time {
371
+ // The template writes the lane geometry as custom properties rather than
372
+ // as `inset-inline-start` / `width` / `height` directly, so the inset can
373
+ // be taken off here: an inline style cannot be adjusted by a stylesheet,
374
+ // and a chip filling its lane to the pixel covered the column line and
375
+ // touched its neighbour in the next lane and the event after it. `top`
376
+ // needs no adjustment and stays an inline `top`.
377
+ inset-inline-start: calc(var(--wr-event-calendar-inline-start) + var(--wr-event-calendar-chip-inset));
378
+ width: calc(var(--wr-event-calendar-inline-size) - 2 * var(--wr-event-calendar-chip-inset));
379
+ height: calc(var(--wr-event-calendar-block-size) - var(--wr-event-calendar-chip-inset));
237
380
  padding: 0.125rem 0.25rem;
238
381
  // The clock and the title share a line while there is room for both and
239
382
  // the title drops below it when there is not. `flex-direction: column`
@@ -250,6 +393,10 @@
250
393
  row-gap: 0;
251
394
  min-height: 1.25rem;
252
395
  white-space: normal;
396
+ // The chip's height is set from outside and never from its content, so
397
+ // size containment costs nothing, and it lets the title ask how many lines
398
+ // the chip holds (see `&-title`).
399
+ container: wr-event-calendar-chip / size;
253
400
  }
254
401
 
255
402
  // A segment clipped by the edge of the view loses the rounding on that side,
@@ -280,8 +427,8 @@
280
427
  // one-slot event has — so the label was clipped through its own digits.
281
428
  white-space: nowrap;
282
429
  // The muted role is calibrated against the plain surface, and the chip
283
- // puts an 18% wash of the event colour under it (line ~192) — which spent
284
- // the whole margin: 4.18–4.28:1 across the shipped demo colours, under AA
430
+ // puts an 18% wash of the event colour under it (its `background`) — which
431
+ // spent the whole margin: 4.18–4.28:1 across the shipped demo colours, under AA
285
432
  // in LIGHT for every one of them. Mixing toward the page's own ink is the
286
433
  // `-ink` recipe: `--wr-color-on-surface` flips per theme, so one
287
434
  // declaration darkens on a light tint and lightens on a dark one. 85% is
@@ -307,18 +454,28 @@
307
454
  // The one thing in a day cell that is NOT absolutely positioned, and it has
308
455
  // to stay that way. Its lane is `maxLanes` — one past the last chip — so
309
456
  // absolute put it at 1.75rem + 3 x 1.375rem = 5.875rem inside a cell whose
310
- // floor is 5.5rem: the entire button landed in the following week's row,
457
+ // floor was 5.5rem: the entire button landed in the following week's row,
311
458
  // which comes later in the DOM and (correctly, per the `__cell` note above)
312
459
  // has no z-index to lose to it, so it swallowed every click. A block box in
313
- // flow lands on exactly the same 5.875rem — the day-number line box is
314
- // precisely the 1.75rem the chips offset by, so only the lanes have to be
315
- // skipped — and makes the cell GROW to hold it instead. `min-height` on the
316
- // cell is a floor, not a size; the row stretches its siblings to match.
460
+ // flow lands exactly where that lane would start — the day-number line box is
461
+ // precisely the 1.75rem the chips offset by, so only the first gap and the
462
+ // lanes have to be skipped — and makes the cell GROW to hold it instead.
463
+ // `min-height` on the cell is a floor, not a size; the row stretches its
464
+ // siblings to match.
465
+ //
466
+ // It is as tall as a chip. At its own 18px line its centre sat 23px below the
467
+ // centre of the chip above it, one pixel short of the 24px WCAG 2.5.8's
468
+ // spacing exception asks for. axe flagged both targets wherever the cell was
469
+ // narrow enough to put the two centres nearly in line.
317
470
  &__more {
318
471
  display: block;
319
472
  width: fit-content;
320
- margin-top: calc(var(--wr-event-calendar-lane) * (var(--wr-event-calendar-band-height) + 0.125rem));
321
- margin-inline-start: 0.125rem;
473
+ min-height: var(--wr-event-calendar-band-height);
474
+ margin-top: calc(
475
+ var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lane) *
476
+ (var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
477
+ );
478
+ margin-inline-start: var(--wr-event-calendar-chip-inset);
322
479
  padding: 0 0.375rem;
323
480
  font: inherit;
324
481
  font-size: var(--wr-text-xs);
@@ -354,3 +511,20 @@
354
511
  user-select: none;
355
512
  }
356
513
  }
514
+
515
+ // A timed chip with room for ONE line: two of the chip's 1.2 line boxes are
516
+ // 2.4em, and the query measures the content box. There the title stays on the
517
+ // clock's line and ends in an ellipsis. Left to wrap, it dropped to a second
518
+ // line that started 14.4px down a 16px content box, so a one-slot chip showed
519
+ // the top of the title's letters and nothing else. On the docs page that
520
+ // happened at 1280px wide, where the week columns are 118px. A chip narrower
521
+ // than its clock plus the gap still wraps the title, because a container query
522
+ // cannot turn off `flex-wrap` on the chip itself; at that width the clock is
523
+ // already cut off.
524
+ @container wr-event-calendar-chip (height < 2.4em) {
525
+ .wr-event-calendar__chip-title {
526
+ flex: 1 1 0;
527
+ min-width: 0;
528
+ white-space: nowrap;
529
+ }
530
+ }
@@ -1,6 +1,7 @@
1
1
  import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
2
2
  import * as i0 from '@angular/core';
3
- import { input, computed, ViewEncapsulation, Component } from '@angular/core';
3
+ import { input, viewChildren, computed, ViewEncapsulation, Component } from '@angular/core';
4
+ import { useChartTooltip } from 'ngwr/popover';
4
5
 
5
6
  /**
6
7
  * @license
@@ -35,6 +36,13 @@ class WrBarChart {
35
36
  height = input(200, { ...(ngDevMode ? { debugName: "height" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(40, coerceNumberProperty(v, 200)) });
36
37
  /** Explicit max value. `0` = auto. @default 0 */
37
38
  max = input(0, { ...(ngDevMode ? { debugName: "max" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, coerceNumberProperty(v, 0)) });
39
+ /**
40
+ * Show a tooltip with the bar's label and value on hover. Pointer only — the
41
+ * column's accessible name already carries both. @default true
42
+ */
43
+ tooltip = input(true, { ...(ngDevMode ? { debugName: "tooltip" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
44
+ barEls = viewChildren('barEl', /* @ts-ignore */
45
+ ...(ngDevMode ? [{ debugName: "barEls" }] : /* istanbul ignore next */ []));
38
46
  /**
39
47
  * A datum's value, with anything non-finite read as `0`.
40
48
  *
@@ -74,13 +82,30 @@ class WrBarChart {
74
82
  };
75
83
  }), /* @ts-ignore */
76
84
  ...(ngDevMode ? [{ debugName: "bars" }] : /* istanbul ignore next */ []));
85
+ /**
86
+ * One tooltip for the whole chart, with the value exactly as it is printed above
87
+ * the bar. It points at the top edge of the BAR — above it, below it when there is
88
+ * no room — rather than at the column, which is the full height of the plot and
89
+ * would put the chip above every bar alike. A bar with nothing to draw (zero, a
90
+ * negative value) keeps its 1px floor on the baseline, so its chip points there.
91
+ *
92
+ * The bar is the anchor element itself, so an open chip follows it through the
93
+ * height transition a data change starts.
94
+ */
95
+ tip = useChartTooltip(this.tooltip, index => {
96
+ const bar = this.bars()[index];
97
+ const anchor = this.barEls()[index]?.nativeElement;
98
+ if (!bar || !anchor)
99
+ return null;
100
+ return { datum: { label: bar.label, value: String(bar.value), color: bar.color }, anchor };
101
+ });
77
102
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrBarChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
78
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrBarChart, isStandalone: true, selector: "wr-bar-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-bar-chart" }, ngImport: i0, template: "<div class=\"wr-bar-chart__plot\" [style.height.px]=\"height()\">\n @for (bar of bars(); track $index) {\n <div class=\"wr-bar-chart__column\" role=\"img\" [attr.aria-label]=\"bar.name\">\n @if (showValues()) {\n <span class=\"wr-bar-chart__value\">{{ bar.value }}</span>\n }\n <div class=\"wr-bar-chart__bar\" [style.height.%]=\"bar.heightPercent\" [style.background]=\"bar.color\"></div>\n </div>\n }\n</div>\n<!-- Named on the column above, so the visible label row is decoration here. -->\n<div class=\"wr-bar-chart__labels\" aria-hidden=\"true\">\n @for (bar of bars(); track $index) {\n <span class=\"wr-bar-chart__label\">{{ bar.label }}</span>\n }\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
103
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrBarChart, isStandalone: true, selector: "wr-bar-chart", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, showValues: { classPropertyName: "showValues", publicName: "showValues", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-bar-chart" }, viewQueries: [{ propertyName: "barEls", predicate: ["barEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"wr-bar-chart__plot\" [style.height.px]=\"height()\">\n @for (bar of bars(); track $index) {\n <div\n class=\"wr-bar-chart__column\"\n role=\"img\"\n [attr.aria-label]=\"bar.name\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n >\n @if (showValues()) {\n <span class=\"wr-bar-chart__value\">{{ bar.value }}</span>\n }\n <div #barEl class=\"wr-bar-chart__bar\" [style.height.%]=\"bar.heightPercent\" [style.background]=\"bar.color\"></div>\n </div>\n }\n</div>\n<!-- Named on the column above, so the visible label row is decoration here. -->\n<div class=\"wr-bar-chart__labels\" aria-hidden=\"true\">\n @for (bar of bars(); track $index) {\n <span class=\"wr-bar-chart__label\">{{ bar.label }}</span>\n }\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
79
104
  }
80
105
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrBarChart, decorators: [{
81
106
  type: Component,
82
- args: [{ selector: 'wr-bar-chart', encapsulation: ViewEncapsulation.None, host: { class: 'wr-bar-chart' }, template: "<div class=\"wr-bar-chart__plot\" [style.height.px]=\"height()\">\n @for (bar of bars(); track $index) {\n <div class=\"wr-bar-chart__column\" role=\"img\" [attr.aria-label]=\"bar.name\">\n @if (showValues()) {\n <span class=\"wr-bar-chart__value\">{{ bar.value }}</span>\n }\n <div class=\"wr-bar-chart__bar\" [style.height.%]=\"bar.heightPercent\" [style.background]=\"bar.color\"></div>\n </div>\n }\n</div>\n<!-- Named on the column above, so the visible label row is decoration here. -->\n<div class=\"wr-bar-chart__labels\" aria-hidden=\"true\">\n @for (bar of bars(); track $index) {\n <span class=\"wr-bar-chart__label\">{{ bar.label }}</span>\n }\n</div>\n" }]
83
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }] } });
107
+ args: [{ selector: 'wr-bar-chart', encapsulation: ViewEncapsulation.None, host: { class: 'wr-bar-chart' }, template: "<div class=\"wr-bar-chart__plot\" [style.height.px]=\"height()\">\n @for (bar of bars(); track $index) {\n <div\n class=\"wr-bar-chart__column\"\n role=\"img\"\n [attr.aria-label]=\"bar.name\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n >\n @if (showValues()) {\n <span class=\"wr-bar-chart__value\">{{ bar.value }}</span>\n }\n <div #barEl class=\"wr-bar-chart__bar\" [style.height.%]=\"bar.heightPercent\" [style.background]=\"bar.color\"></div>\n </div>\n }\n</div>\n<!-- Named on the column above, so the visible label row is decoration here. -->\n<div class=\"wr-bar-chart__labels\" aria-hidden=\"true\">\n @for (bar of bars(); track $index) {\n <span class=\"wr-bar-chart__label\">{{ bar.label }}</span>\n }\n</div>\n" }]
108
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], showValues: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValues", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], barEls: [{ type: i0.ViewChildren, args: ['barEl', { isSignal: true }] }] } });
84
109
 
85
110
  /**
86
111
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"ngwr-bar-chart.mjs","sources":["../../../projects/lib/bar-chart/bar-chart.ts","../../../projects/lib/bar-chart/bar-chart.html","../../../projects/lib/bar-chart/ngwr-bar-chart.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input } from '@angular/core';\n\nimport type { WrBarChartDatum } from './interfaces';\n\n/**\n * Minimal vertical bar chart. Pass `[data]` — each datum becomes a bar.\n * Axis-free; for the simple \"show me a comparison\" case.\n *\n * @example\n * ```html\n * <wr-bar-chart [data]=\"[\n * { label: 'Mon', value: 12 },\n * { label: 'Tue', value: 18, color: 'var(--wr-color-success)' },\n * { label: 'Wed', value: 9 }\n * ]\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/bar-chart\n */\n@Component({\n selector: 'wr-bar-chart',\n templateUrl: './bar-chart.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-bar-chart' },\n})\nexport class WrBarChart {\n readonly data = input<readonly WrBarChartDatum[]>([]);\n\n /** Default bar colour when a datum has none. @default primary */\n readonly color = input<string>('var(--wr-color-primary)');\n\n /** Show value labels above each bar. @default true */\n readonly showValues = input(true, { transform: coerceBooleanProperty });\n\n /** Pixel height of the chart area. @default 200 */\n readonly height = input(200, { transform: (v: unknown): number => Math.max(40, coerceNumberProperty(v, 200)) });\n\n /** Explicit max value. `0` = auto. @default 0 */\n readonly max = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /**\n * A datum's value, with anything non-finite read as `0`.\n *\n * One `NaN` used to take out the whole chart rather than its own bar:\n * `Math.max(...values)` is `NaN` as soon as one value is, so the scale fell\n * back to `1` and every OTHER bar was asked for a height of `value * 100`%.\n * The bad bar also printed the literal text `NaN` above itself.\n */\n private static value(raw: number): number {\n return Number.isFinite(raw) ? raw : 0;\n }\n\n protected readonly resolvedMax = computed(() => {\n const explicit = this.max();\n if (explicit > 0) return explicit;\n const data = this.data();\n if (data.length === 0) return 1;\n const top = Math.max(...data.map(d => WrBarChart.value(d.value)), 0);\n return top > 0 ? top : 1;\n });\n\n protected readonly bars = computed(() =>\n this.data().map(d => {\n const value = WrBarChart.value(d.value);\n return {\n label: d.label,\n value,\n color: d.color ?? this.color(),\n heightPercent: (Math.max(0, value) / this.resolvedMax()) * 100,\n /**\n * The bar's accessible name. The label and the value sit in separate\n * rows, so a screen reader read every number and then every label with\n * nothing tying the two together — and with `showValues` off the\n * numbers were not in the accessible tree at all.\n */\n name: `${d.label}: ${value}`,\n };\n })\n );\n}\n\nexport type { WrBarChartDatum } from './interfaces';\n","<div class=\"wr-bar-chart__plot\" [style.height.px]=\"height()\">\n @for (bar of bars(); track $index) {\n <div class=\"wr-bar-chart__column\" role=\"img\" [attr.aria-label]=\"bar.name\">\n @if (showValues()) {\n <span class=\"wr-bar-chart__value\">{{ bar.value }}</span>\n }\n <div class=\"wr-bar-chart__bar\" [style.height.%]=\"bar.heightPercent\" [style.background]=\"bar.color\"></div>\n </div>\n }\n</div>\n<!-- Named on the column above, so the visible label row is decoration here. -->\n<div class=\"wr-bar-chart__labels\" aria-hidden=\"true\">\n @for (bar of bars(); track $index) {\n <span class=\"wr-bar-chart__label\">{{ bar.label }}</span>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngwr-bar-chart.mjs","sources":["../../../projects/lib/bar-chart/bar-chart.ts","../../../projects/lib/bar-chart/bar-chart.html","../../../projects/lib/bar-chart/ngwr-bar-chart.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, type ElementRef, ViewEncapsulation, computed, input, viewChildren } from '@angular/core';\n\nimport { useChartTooltip } from 'ngwr/popover';\n\nimport type { WrBarChartDatum } from './interfaces';\n\n/**\n * Minimal vertical bar chart. Pass `[data]` — each datum becomes a bar.\n * Axis-free; for the simple \"show me a comparison\" case.\n *\n * @example\n * ```html\n * <wr-bar-chart [data]=\"[\n * { label: 'Mon', value: 12 },\n * { label: 'Tue', value: 18, color: 'var(--wr-color-success)' },\n * { label: 'Wed', value: 9 }\n * ]\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/bar-chart\n */\n@Component({\n selector: 'wr-bar-chart',\n templateUrl: './bar-chart.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-bar-chart' },\n})\nexport class WrBarChart {\n readonly data = input<readonly WrBarChartDatum[]>([]);\n\n /** Default bar colour when a datum has none. @default primary */\n readonly color = input<string>('var(--wr-color-primary)');\n\n /** Show value labels above each bar. @default true */\n readonly showValues = input(true, { transform: coerceBooleanProperty });\n\n /** Pixel height of the chart area. @default 200 */\n readonly height = input(200, { transform: (v: unknown): number => Math.max(40, coerceNumberProperty(v, 200)) });\n\n /** Explicit max value. `0` = auto. @default 0 */\n readonly max = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /**\n * Show a tooltip with the bar's label and value on hover. Pointer only — the\n * column's accessible name already carries both. @default true\n */\n readonly tooltip = input(true, { transform: coerceBooleanProperty });\n\n private readonly barEls = viewChildren<ElementRef<HTMLElement>>('barEl');\n\n /**\n * A datum's value, with anything non-finite read as `0`.\n *\n * One `NaN` used to take out the whole chart rather than its own bar:\n * `Math.max(...values)` is `NaN` as soon as one value is, so the scale fell\n * back to `1` and every OTHER bar was asked for a height of `value * 100`%.\n * The bad bar also printed the literal text `NaN` above itself.\n */\n private static value(raw: number): number {\n return Number.isFinite(raw) ? raw : 0;\n }\n\n protected readonly resolvedMax = computed(() => {\n const explicit = this.max();\n if (explicit > 0) return explicit;\n const data = this.data();\n if (data.length === 0) return 1;\n const top = Math.max(...data.map(d => WrBarChart.value(d.value)), 0);\n return top > 0 ? top : 1;\n });\n\n protected readonly bars = computed(() =>\n this.data().map(d => {\n const value = WrBarChart.value(d.value);\n return {\n label: d.label,\n value,\n color: d.color ?? this.color(),\n heightPercent: (Math.max(0, value) / this.resolvedMax()) * 100,\n /**\n * The bar's accessible name. The label and the value sit in separate\n * rows, so a screen reader read every number and then every label with\n * nothing tying the two together — and with `showValues` off the\n * numbers were not in the accessible tree at all.\n */\n name: `${d.label}: ${value}`,\n };\n })\n );\n\n /**\n * One tooltip for the whole chart, with the value exactly as it is printed above\n * the bar. It points at the top edge of the BAR — above it, below it when there is\n * no room — rather than at the column, which is the full height of the plot and\n * would put the chip above every bar alike. A bar with nothing to draw (zero, a\n * negative value) keeps its 1px floor on the baseline, so its chip points there.\n *\n * The bar is the anchor element itself, so an open chip follows it through the\n * height transition a data change starts.\n */\n protected readonly tip = useChartTooltip(this.tooltip, index => {\n const bar = this.bars()[index];\n const anchor = this.barEls()[index]?.nativeElement;\n if (!bar || !anchor) return null;\n return { datum: { label: bar.label, value: String(bar.value), color: bar.color }, anchor };\n });\n}\n\nexport type { WrBarChartDatum } from './interfaces';\n","<div class=\"wr-bar-chart__plot\" [style.height.px]=\"height()\">\n @for (bar of bars(); track $index) {\n <div\n class=\"wr-bar-chart__column\"\n role=\"img\"\n [attr.aria-label]=\"bar.name\"\n (mouseenter)=\"tip.enter($index)\"\n (mouseleave)=\"tip.leave($event)\"\n >\n @if (showValues()) {\n <span class=\"wr-bar-chart__value\">{{ bar.value }}</span>\n }\n <div #barEl class=\"wr-bar-chart__bar\" [style.height.%]=\"bar.heightPercent\" [style.background]=\"bar.color\"></div>\n </div>\n }\n</div>\n<!-- Named on the column above, so the visible label row is decoration here. -->\n<div class=\"wr-bar-chart__labels\" aria-hidden=\"true\">\n @for (bar of bars(); track $index) {\n <span class=\"wr-bar-chart__label\">{{ bar.label }}</span>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
2
2
  import * as i0 from '@angular/core';
3
- import { input, inject, computed, ViewEncapsulation, Component } from '@angular/core';
3
+ import { input, viewChild, inject, computed, ViewEncapsulation, Component } from '@angular/core';
4
4
  import { WR_DATE_LOCALE } from 'ngwr/date';
5
5
  import { useI18nText, useI18nFormatter } from 'ngwr/i18n';
6
+ import { useChartTooltip } from 'ngwr/popover';
6
7
 
7
8
  /**
8
9
  * @license
@@ -95,6 +96,14 @@ class WrCalendarHeatmap {
95
96
  ...(ngDevMode ? [{ debugName: "emptyColor" }] : /* istanbul ignore next */ []));
96
97
  /** Show the weekday + month labels around the grid. @default true */
97
98
  showLabels = input(true, { ...(ngDevMode ? { debugName: "showLabels" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
99
+ /**
100
+ * Show a tooltip with the day and its count on hover. It is the sentence the
101
+ * square's `title` carried, so the `title` is written only while this is off —
102
+ * or the browser would open a second copy a moment later. @default true
103
+ */
104
+ tooltip = input(true, { ...(ngDevMode ? { debugName: "tooltip" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
105
+ daysEl = viewChild('days', /* @ts-ignore */
106
+ ...(ngDevMode ? [{ debugName: "daysEl" }] : /* istanbul ignore next */ []));
98
107
  locale = inject(WR_DATE_LOCALE);
99
108
  /**
100
109
  * Weekday names from the locale rather than a hard-coded English list — the row order is
@@ -184,6 +193,52 @@ class WrCalendarHeatmap {
184
193
  return cells.length === 0 ? 0 : cells[cells.length - 1].week + 1;
185
194
  }, /* @ts-ignore */
186
195
  ...(ngDevMode ? [{ debugName: "columnCount" }] : /* istanbul ignore next */ []));
196
+ /** Each day's position in `cells()`, for the square the pointer lands on. */
197
+ indexByIso = computed(() => new Map(this.cells().map((cell, index) => [cell.iso, index])), /* @ts-ignore */
198
+ ...(ngDevMode ? [{ debugName: "indexByIso" }] : /* istanbul ignore next */ []));
199
+ /**
200
+ * One tooltip for the whole year, pointing at the hovered day: above its square,
201
+ * below it when there is no room above, and slid along the viewport edge for the
202
+ * first and last weeks with the arrow still on the square. A listener on the grid
203
+ * rather than one per square: a year is 371 of them.
204
+ *
205
+ * The box is the square's LAYOUT box rather than its client rect. The hovered square
206
+ * grows by `:hover` over a transition, and a rect read part way through it would
207
+ * move the chip by up to a fifth of a square depending on when it was measured;
208
+ * the scale is centred, so the layout box is the rect's centre and the square's
209
+ * own size.
210
+ */
211
+ tip = useChartTooltip(this.tooltip, index => {
212
+ const cell = this.cells()[index];
213
+ // The squares are the container's only children, drawn in `cells()` order.
214
+ const square = cell ? this.daysEl()?.nativeElement.children.item(index) : null;
215
+ if (!cell || !(square instanceof HTMLElement))
216
+ return null;
217
+ const rect = square.getBoundingClientRect();
218
+ const width = square.offsetWidth;
219
+ const height = square.offsetHeight;
220
+ return {
221
+ datum: { value: this.cellTitle(cell) },
222
+ anchor: {
223
+ x: (rect.left + rect.right - width) / 2,
224
+ y: (rect.top + rect.bottom - height) / 2,
225
+ width,
226
+ height,
227
+ },
228
+ };
229
+ });
230
+ /**
231
+ * Which square the pointer is on, from a `mousemove` on the grid. Over the gap
232
+ * between two squares it is on none, and the tooltip starts to leave.
233
+ */
234
+ onCellsPointer(event) {
235
+ const iso = event.target?.closest('.wr-calendar-heatmap__cell')?.dataset['date'];
236
+ const index = iso === undefined ? undefined : this.indexByIso().get(iso);
237
+ if (index === undefined)
238
+ this.tip.leave(event);
239
+ else
240
+ this.tip.enter(index);
241
+ }
187
242
  colorFor(intensity) {
188
243
  if (intensity === 0)
189
244
  return this.emptyColor();
@@ -202,12 +257,12 @@ class WrCalendarHeatmap {
202
257
  return 1;
203
258
  }
204
259
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrCalendarHeatmap, deps: [], target: i0.ɵɵFactoryTarget.Component });
205
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrCalendarHeatmap, isStandalone: true, selector: "wr-calendar-heatmap", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, endDate: { classPropertyName: "endDate", publicName: "endDate", isSignal: true, isRequired: false, transformFunction: null }, weeks: { classPropertyName: "weeks", publicName: "weeks", isSignal: true, isRequired: false, transformFunction: null }, cellSize: { classPropertyName: "cellSize", publicName: "cellSize", isSignal: true, isRequired: false, transformFunction: null }, cellGap: { classPropertyName: "cellGap", publicName: "cellGap", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, emptyColor: { classPropertyName: "emptyColor", publicName: "emptyColor", isSignal: true, isRequired: false, transformFunction: null }, showLabels: { classPropertyName: "showLabels", publicName: "showLabels", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-calendar-heatmap" }, ngImport: i0, template: "<div\n class=\"wr-calendar-heatmap__grid\"\n role=\"img\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [style.--wr-heatmap-cell-size.px]=\"cellSize()\"\n [style.--wr-heatmap-cell-gap.px]=\"cellGap()\"\n [style.--wr-heatmap-columns]=\"columnCount()\"\n>\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__weekdays\">\n @for (label of weekdayLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__weekday\">{{ label }}</span>\n }\n </div>\n }\n\n <div class=\"wr-calendar-heatmap__cells\">\n @for (cell of cells(); track cell.iso) {\n <span\n class=\"wr-calendar-heatmap__cell\"\n [style.background]=\"colorFor(cell.intensity)\"\n [style.opacity]=\"opacityFor(cell.intensity)\"\n [style.grid-column]=\"cell.week + 1\"\n [style.grid-row]=\"cell.day + 1\"\n [title]=\"cellTitle(cell)\"\n [attr.data-date]=\"cell.iso\"\n [attr.data-value]=\"cell.value\"\n aria-hidden=\"true\"\n ></span>\n }\n </div>\n\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__months\">\n @for (m of monthLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__month\" [style.grid-column]=\"m.week + 1\">{{ m.label }}</span>\n }\n </div>\n }\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
260
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrCalendarHeatmap, isStandalone: true, selector: "wr-calendar-heatmap", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, endDate: { classPropertyName: "endDate", publicName: "endDate", isSignal: true, isRequired: false, transformFunction: null }, weeks: { classPropertyName: "weeks", publicName: "weeks", isSignal: true, isRequired: false, transformFunction: null }, cellSize: { classPropertyName: "cellSize", publicName: "cellSize", isSignal: true, isRequired: false, transformFunction: null }, cellGap: { classPropertyName: "cellGap", publicName: "cellGap", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, emptyColor: { classPropertyName: "emptyColor", publicName: "emptyColor", isSignal: true, isRequired: false, transformFunction: null }, showLabels: { classPropertyName: "showLabels", publicName: "showLabels", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-calendar-heatmap" }, viewQueries: [{ propertyName: "daysEl", first: true, predicate: ["days"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"wr-calendar-heatmap__grid\"\n role=\"img\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [style.--wr-heatmap-cell-size.px]=\"cellSize()\"\n [style.--wr-heatmap-cell-gap.px]=\"cellGap()\"\n [style.--wr-heatmap-columns]=\"columnCount()\"\n>\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__weekdays\">\n @for (label of weekdayLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__weekday\">{{ label }}</span>\n }\n </div>\n }\n\n <div #days class=\"wr-calendar-heatmap__cells\" (mousemove)=\"onCellsPointer($event)\" (mouseleave)=\"tip.leave($event)\">\n @for (cell of cells(); track cell.iso) {\n <span\n class=\"wr-calendar-heatmap__cell\"\n [style.background]=\"colorFor(cell.intensity)\"\n [style.opacity]=\"opacityFor(cell.intensity)\"\n [style.grid-column]=\"cell.week + 1\"\n [style.grid-row]=\"cell.day + 1\"\n [attr.title]=\"tooltip() ? null : cellTitle(cell)\"\n [attr.data-date]=\"cell.iso\"\n [attr.data-value]=\"cell.value\"\n aria-hidden=\"true\"\n ></span>\n }\n </div>\n\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__months\">\n @for (m of monthLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__month\" [style.grid-column]=\"m.week + 1\">{{ m.label }}</span>\n }\n </div>\n }\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
206
261
  }
207
262
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrCalendarHeatmap, decorators: [{
208
263
  type: Component,
209
- args: [{ selector: 'wr-calendar-heatmap', encapsulation: ViewEncapsulation.None, host: { class: 'wr-calendar-heatmap' }, template: "<div\n class=\"wr-calendar-heatmap__grid\"\n role=\"img\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [style.--wr-heatmap-cell-size.px]=\"cellSize()\"\n [style.--wr-heatmap-cell-gap.px]=\"cellGap()\"\n [style.--wr-heatmap-columns]=\"columnCount()\"\n>\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__weekdays\">\n @for (label of weekdayLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__weekday\">{{ label }}</span>\n }\n </div>\n }\n\n <div class=\"wr-calendar-heatmap__cells\">\n @for (cell of cells(); track cell.iso) {\n <span\n class=\"wr-calendar-heatmap__cell\"\n [style.background]=\"colorFor(cell.intensity)\"\n [style.opacity]=\"opacityFor(cell.intensity)\"\n [style.grid-column]=\"cell.week + 1\"\n [style.grid-row]=\"cell.day + 1\"\n [title]=\"cellTitle(cell)\"\n [attr.data-date]=\"cell.iso\"\n [attr.data-value]=\"cell.value\"\n aria-hidden=\"true\"\n ></span>\n }\n </div>\n\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__months\">\n @for (m of monthLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__month\" [style.grid-column]=\"m.week + 1\">{{ m.label }}</span>\n }\n </div>\n }\n</div>\n" }]
210
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], endDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "endDate", required: false }] }], weeks: [{ type: i0.Input, args: [{ isSignal: true, alias: "weeks", required: false }] }], cellSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellSize", required: false }] }], cellGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellGap", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], emptyColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyColor", required: false }] }], showLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabels", required: false }] }] } });
264
+ args: [{ selector: 'wr-calendar-heatmap', encapsulation: ViewEncapsulation.None, host: { class: 'wr-calendar-heatmap' }, template: "<div\n class=\"wr-calendar-heatmap__grid\"\n role=\"img\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [style.--wr-heatmap-cell-size.px]=\"cellSize()\"\n [style.--wr-heatmap-cell-gap.px]=\"cellGap()\"\n [style.--wr-heatmap-columns]=\"columnCount()\"\n>\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__weekdays\">\n @for (label of weekdayLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__weekday\">{{ label }}</span>\n }\n </div>\n }\n\n <div #days class=\"wr-calendar-heatmap__cells\" (mousemove)=\"onCellsPointer($event)\" (mouseleave)=\"tip.leave($event)\">\n @for (cell of cells(); track cell.iso) {\n <span\n class=\"wr-calendar-heatmap__cell\"\n [style.background]=\"colorFor(cell.intensity)\"\n [style.opacity]=\"opacityFor(cell.intensity)\"\n [style.grid-column]=\"cell.week + 1\"\n [style.grid-row]=\"cell.day + 1\"\n [attr.title]=\"tooltip() ? null : cellTitle(cell)\"\n [attr.data-date]=\"cell.iso\"\n [attr.data-value]=\"cell.value\"\n aria-hidden=\"true\"\n ></span>\n }\n </div>\n\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__months\">\n @for (m of monthLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__month\" [style.grid-column]=\"m.week + 1\">{{ m.label }}</span>\n }\n </div>\n }\n</div>\n" }]
265
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], endDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "endDate", required: false }] }], weeks: [{ type: i0.Input, args: [{ isSignal: true, alias: "weeks", required: false }] }], cellSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellSize", required: false }] }], cellGap: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellGap", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], emptyColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyColor", required: false }] }], showLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabels", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }], daysEl: [{ type: i0.ViewChild, args: ['days', { isSignal: true }] }] } });
211
266
 
212
267
  /**
213
268
  * Generated bundle index. Do not edit.