@brandsync/wc 1.9.0 → 1.10.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 (229) hide show
  1. package/custom-elements.json +4520 -3613
  2. package/dist/brandsync-wc/brandsync-wc.esm.js +1 -1
  3. package/dist/brandsync-wc/{p-c4de155c.entry.js → p-0132a2d1.entry.js} +1 -1
  4. package/dist/brandsync-wc/{p-051d3064.entry.js → p-041776c0.entry.js} +1 -1
  5. package/dist/brandsync-wc/{p-a09e157f.entry.js → p-08c99a60.entry.js} +1 -1
  6. package/dist/brandsync-wc/{p-70f64b25.entry.js → p-18c3c22c.entry.js} +1 -1
  7. package/dist/brandsync-wc/p-1c3a43c7.entry.js +1 -0
  8. package/dist/brandsync-wc/{p-fddc7bd1.entry.js → p-1c427ffb.entry.js} +1 -1
  9. package/dist/brandsync-wc/{p-29027559.entry.js → p-2e958566.entry.js} +1 -1
  10. package/dist/brandsync-wc/{p-235ae012.entry.js → p-301b2455.entry.js} +1 -1
  11. package/dist/brandsync-wc/{p-8ee0153b.entry.js → p-32cd69f1.entry.js} +1 -1
  12. package/dist/brandsync-wc/p-4f2c4929.entry.js +1 -0
  13. package/dist/brandsync-wc/{p-a0d5a620.entry.js → p-50a251a4.entry.js} +1 -1
  14. package/dist/brandsync-wc/{p-0e39b9cc.entry.js → p-5f3cd501.entry.js} +1 -1
  15. package/dist/brandsync-wc/{p-fc240aa0.entry.js → p-701ebf4a.entry.js} +1 -1
  16. package/dist/brandsync-wc/{p-0eed6813.entry.js → p-763876f5.entry.js} +1 -1
  17. package/dist/brandsync-wc/{p-f7d47c17.entry.js → p-76e1c295.entry.js} +1 -1
  18. package/dist/brandsync-wc/p-790db8b3.entry.js +1 -0
  19. package/dist/brandsync-wc/{p-4e5dcaff.entry.js → p-796a1860.entry.js} +1 -1
  20. package/dist/brandsync-wc/{p-36bf37d9.entry.js → p-806a5347.entry.js} +1 -1
  21. package/dist/brandsync-wc/{p-6331de9c.entry.js → p-8eba7f90.entry.js} +1 -1
  22. package/dist/brandsync-wc/{p-6fd7dd6a.entry.js → p-96ed9386.entry.js} +1 -1
  23. package/dist/brandsync-wc/{p-cfcf3f0a.entry.js → p-9e88f19c.entry.js} +1 -1
  24. package/dist/brandsync-wc/{p-de7c946d.entry.js → p-a71d2811.entry.js} +1 -1
  25. package/dist/brandsync-wc/{p-33e44094.entry.js → p-a8e2a829.entry.js} +1 -1
  26. package/dist/brandsync-wc/{p-3b64e3cd.entry.js → p-addfa0a0.entry.js} +1 -1
  27. package/dist/brandsync-wc/{p-4574a707.entry.js → p-af2bf957.entry.js} +1 -1
  28. package/dist/brandsync-wc/{p-6bf2f116.entry.js → p-b2074a32.entry.js} +1 -1
  29. package/dist/brandsync-wc/{p-7c94e6ae.entry.js → p-c99b6a66.entry.js} +1 -1
  30. package/dist/brandsync-wc/{p-2891d40b.entry.js → p-c9a72416.entry.js} +1 -1
  31. package/dist/brandsync-wc/{p-9f65f998.entry.js → p-d3f44cb7.entry.js} +1 -1
  32. package/dist/brandsync-wc/p-d42b1c2b.entry.js +1 -0
  33. package/dist/brandsync-wc/{p-3ec74d35.entry.js → p-daab6b22.entry.js} +1 -1
  34. package/dist/brandsync-wc/{p-107b1c5d.entry.js → p-dbcbe682.entry.js} +1 -1
  35. package/dist/brandsync-wc/{p-3176d1d3.entry.js → p-e8a5b8eb.entry.js} +1 -1
  36. package/dist/brandsync-wc/{p-062cfa34.entry.js → p-ea4e20ef.entry.js} +1 -1
  37. package/dist/brandsync-wc/{p-27bbed83.entry.js → p-f370b8fa.entry.js} +1 -1
  38. package/dist/brandsync-wc/{p-05c7de28.entry.js → p-f89de457.entry.js} +1 -1
  39. package/dist/brandsync-wc/{p-114d2fd8.entry.js → p-fd254972.entry.js} +1 -1
  40. package/dist/cjs/brandsync-wc.cjs.js +1 -1
  41. package/dist/cjs/bs-ai-disclaimer.cjs.entry.js +1 -1
  42. package/dist/cjs/bs-ai-greeting.cjs.entry.js +1 -1
  43. package/dist/cjs/bs-ai-thinking.cjs.entry.js +1 -1
  44. package/dist/cjs/bs-attachment-list.cjs.entry.js +1 -1
  45. package/dist/cjs/bs-breadcrumbs.cjs.entry.js +1 -1
  46. package/dist/cjs/bs-button-skeleton.cjs.entry.js +1 -1
  47. package/dist/cjs/bs-chatbot-feedback.cjs.entry.js +1 -1
  48. package/dist/cjs/bs-chatbot-header.cjs.entry.js +1 -1
  49. package/dist/cjs/bs-chatbot-response-action.cjs.entry.js +1 -1
  50. package/dist/cjs/bs-chatbot-sources-drawer.cjs.entry.js +1 -1
  51. package/dist/cjs/bs-chatbot-suggestion-button.cjs.entry.js +1 -1
  52. package/dist/cjs/bs-checkbox-skeleton.cjs.entry.js +1 -1
  53. package/dist/cjs/bs-datepicker.cjs.entry.js +410 -0
  54. package/dist/cjs/bs-file-upload-item.cjs.entry.js +1 -1
  55. package/dist/cjs/bs-file-upload.cjs.entry.js +1 -1
  56. package/dist/cjs/bs-icon-button.cjs.entry.js +1 -1
  57. package/dist/cjs/bs-inline-tab.cjs.entry.js +1 -1
  58. package/dist/cjs/{bs-input.cjs.entry.js → bs-input_2.cjs.entry.js} +37 -4
  59. package/dist/cjs/bs-menu.cjs.entry.js +1 -1
  60. package/dist/cjs/bs-navigation-drawer-item.cjs.entry.js +1 -1
  61. package/dist/cjs/bs-navigation-drawer.cjs.entry.js +2 -2
  62. package/dist/cjs/bs-navigation-header.cjs.entry.js +1 -1
  63. package/dist/cjs/bs-pagination.cjs.entry.js +1 -1
  64. package/dist/cjs/bs-progress-linear.cjs.entry.js +2 -2
  65. package/dist/cjs/bs-progress.cjs.entry.js +2 -2
  66. package/dist/cjs/bs-radio.cjs.entry.js +1 -1
  67. package/dist/cjs/bs-slider.cjs.entry.js +1 -1
  68. package/dist/cjs/bs-snackbar.cjs.entry.js +1 -1
  69. package/dist/cjs/bs-source-link.cjs.entry.js +2 -2
  70. package/dist/cjs/bs-stepper-step.cjs.entry.js +1 -1
  71. package/dist/cjs/bs-stepper.cjs.entry.js +1 -1
  72. package/dist/cjs/bs-switch.cjs.entry.js +1 -1
  73. package/dist/cjs/bs-tab.cjs.entry.js +1 -1
  74. package/dist/cjs/bs-tabs.cjs.entry.js +1 -1
  75. package/dist/cjs/bs-timepicker.cjs.entry.js +209 -0
  76. package/dist/cjs/bs-toast.cjs.entry.js +1 -1
  77. package/dist/cjs/bs-tooltip.cjs.entry.js +1 -1
  78. package/dist/cjs/loader.cjs.js +1 -1
  79. package/dist/collection/collection-manifest.json +2 -0
  80. package/dist/collection/components/bs-a11y.cmp.test.js +4 -0
  81. package/dist/collection/components/bs-ai-disclaimer/bs-ai-disclaimer.js +1 -1
  82. package/dist/collection/components/bs-ai-greeting/bs-ai-greeting.js +1 -1
  83. package/dist/collection/components/bs-ai-thinking/bs-ai-thinking.js +1 -1
  84. package/dist/collection/components/bs-attachment-list/bs-attachment-list.js +1 -1
  85. package/dist/collection/components/bs-breadcrumb/bs-breadcrumbs/bs-breadcrumbs.js +1 -1
  86. package/dist/collection/components/bs-button/bs-icon-button/bs-icon-button.js +1 -1
  87. package/dist/collection/components/bs-button-skeleton/bs-button-skeleton.js +1 -1
  88. package/dist/collection/components/bs-chatbot-feedback/bs-chatbot-feedback.js +1 -1
  89. package/dist/collection/components/bs-chatbot-header/bs-chatbot-header.js +1 -1
  90. package/dist/collection/components/bs-chatbot-response-action/bs-chatbot-response-action.js +1 -1
  91. package/dist/collection/components/bs-chatbot-sources-drawer/bs-chatbot-sources-drawer.js +1 -1
  92. package/dist/collection/components/bs-chatbot-suggestion-button/bs-chatbot-suggestion-button.js +1 -1
  93. package/dist/collection/components/bs-checkbox/bs-checkbox-skeleton/bs-checkbox-skeleton.js +1 -1
  94. package/dist/collection/components/bs-datepicker/bs-datepicker.cmp.test.js +182 -0
  95. package/dist/collection/components/bs-datepicker/bs-datepicker.css +315 -0
  96. package/dist/collection/components/bs-datepicker/bs-datepicker.js +782 -0
  97. package/dist/collection/components/bs-datepicker/bs-datepicker.stories.js +63 -0
  98. package/dist/collection/components/bs-file-upload/bs-file-upload.js +1 -1
  99. package/dist/collection/components/bs-file-upload-item/bs-file-upload-item.js +1 -1
  100. package/dist/collection/components/bs-input/bs-input.js +7 -4
  101. package/dist/collection/components/bs-menu/bs-menu.js +1 -1
  102. package/dist/collection/components/bs-menu-item/bs-menu-item.js +1 -1
  103. package/dist/collection/components/bs-pagination/bs-pagination.js +1 -1
  104. package/dist/collection/components/bs-progress/bs-progress.js +2 -2
  105. package/dist/collection/components/bs-progress-linear/bs-progress-linear.js +2 -2
  106. package/dist/collection/components/bs-radio/bs-radio.js +1 -1
  107. package/dist/collection/components/bs-slider/bs-slider.js +1 -1
  108. package/dist/collection/components/bs-snackbar/bs-snackbar.js +1 -1
  109. package/dist/collection/components/bs-source-link/bs-source-link.js +2 -2
  110. package/dist/collection/components/bs-stepper/bs-stepper/bs-stepper.js +1 -1
  111. package/dist/collection/components/bs-stepper/bs-stepper-step/bs-stepper-step.js +1 -1
  112. package/dist/collection/components/bs-switch/bs-switch.js +1 -1
  113. package/dist/collection/components/bs-tab/bs-inline-tab/bs-inline-tab.js +1 -1
  114. package/dist/collection/components/bs-tab/bs-tab/bs-tab.js +1 -1
  115. package/dist/collection/components/bs-tab/bs-tabs/bs-tabs.js +1 -1
  116. package/dist/collection/components/bs-timepicker/bs-timepicker.cmp.test.js +141 -0
  117. package/dist/collection/components/bs-timepicker/bs-timepicker.css +200 -0
  118. package/dist/collection/components/bs-timepicker/bs-timepicker.js +509 -0
  119. package/dist/collection/components/bs-timepicker/bs-timepicker.stories.js +44 -0
  120. package/dist/collection/components/bs-toast/bs-toast.js +1 -1
  121. package/dist/collection/components/bs-tooltip/bs-tooltip.js +1 -1
  122. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer/bs-navigation-drawer.js +2 -2
  123. package/dist/collection/components/ui-shell/bs-navigation-drawer/bs-navigation-drawer-item/bs-navigation-drawer-item.js +1 -1
  124. package/dist/collection/components/ui-shell/bs-navigation-header/bs-navigation-header/bs-navigation-header.js +1 -1
  125. package/dist/components/bs-ai-disclaimer.js +1 -1
  126. package/dist/components/bs-ai-greeting.js +1 -1
  127. package/dist/components/bs-ai-thinking.js +1 -1
  128. package/dist/components/bs-attachment-list.js +1 -1
  129. package/dist/components/bs-attachment.js +1 -1
  130. package/dist/components/bs-breadcrumb-overflow.js +1 -1
  131. package/dist/components/bs-breadcrumbs.js +1 -1
  132. package/dist/components/bs-button-skeleton.js +1 -1
  133. package/dist/components/bs-carousel.js +1 -1
  134. package/dist/components/bs-chatbot-feedback.js +1 -1
  135. package/dist/components/bs-chatbot-header.js +1 -1
  136. package/dist/components/bs-chatbot-response-action.js +1 -1
  137. package/dist/components/bs-chatbot-sources-drawer.js +1 -1
  138. package/dist/components/bs-chatbot-suggestion-button.js +1 -1
  139. package/dist/components/bs-checkbox-skeleton.js +1 -1
  140. package/dist/components/bs-datepicker.d.ts +11 -0
  141. package/dist/components/bs-datepicker.js +1 -0
  142. package/dist/components/bs-dialog.js +1 -1
  143. package/dist/components/bs-file-upload-item.js +1 -1
  144. package/dist/components/bs-file-upload.js +1 -1
  145. package/dist/components/bs-icon-button.js +1 -1
  146. package/dist/components/bs-inline-tab.js +1 -1
  147. package/dist/components/bs-input.js +1 -1
  148. package/dist/components/bs-menu-item.js +1 -1
  149. package/dist/components/bs-menu.js +1 -1
  150. package/dist/components/bs-navigation-drawer-item.js +1 -1
  151. package/dist/components/bs-navigation-drawer.js +1 -1
  152. package/dist/components/bs-navigation-header.js +1 -1
  153. package/dist/components/bs-pagination.js +1 -1
  154. package/dist/components/bs-progress-linear.js +1 -1
  155. package/dist/components/bs-progress.js +1 -1
  156. package/dist/components/bs-radio.js +1 -1
  157. package/dist/components/bs-slider.js +1 -1
  158. package/dist/components/bs-snackbar.js +1 -1
  159. package/dist/components/bs-source-link.js +1 -1
  160. package/dist/components/bs-stepper-step.js +1 -1
  161. package/dist/components/bs-stepper.js +1 -1
  162. package/dist/components/bs-switch.js +1 -1
  163. package/dist/components/bs-tab.js +1 -1
  164. package/dist/components/bs-tabs.js +1 -1
  165. package/dist/components/bs-timepicker.d.ts +11 -0
  166. package/dist/components/bs-timepicker.js +1 -0
  167. package/dist/components/bs-toast.js +1 -1
  168. package/dist/components/bs-tooltip.js +1 -1
  169. package/dist/components/{p-BA3c9Rom.js → p-B7Icv1ho.js} +1 -1
  170. package/dist/components/{p-wei0Ija2.js → p-BTvme8CE.js} +1 -1
  171. package/dist/components/{p-BoeorHNv.js → p-BYR_ZC8v.js} +1 -1
  172. package/dist/components/p-Ba860ej1.js +1 -0
  173. package/dist/components/p-CPvqZNO8.js +1 -0
  174. package/dist/components/{p-EtXc94lJ.js → p-DkIVyFOP.js} +1 -1
  175. package/dist/components/{p-BfEyD6Ku.js → p-ZK8p5zax.js} +1 -1
  176. package/dist/components/p-jDO25SfF.js +1 -0
  177. package/dist/esm/brandsync-wc.js +1 -1
  178. package/dist/esm/bs-ai-disclaimer.entry.js +1 -1
  179. package/dist/esm/bs-ai-greeting.entry.js +1 -1
  180. package/dist/esm/bs-ai-thinking.entry.js +1 -1
  181. package/dist/esm/bs-attachment-list.entry.js +1 -1
  182. package/dist/esm/bs-breadcrumbs.entry.js +1 -1
  183. package/dist/esm/bs-button-skeleton.entry.js +1 -1
  184. package/dist/esm/bs-chatbot-feedback.entry.js +1 -1
  185. package/dist/esm/bs-chatbot-header.entry.js +1 -1
  186. package/dist/esm/bs-chatbot-response-action.entry.js +1 -1
  187. package/dist/esm/bs-chatbot-sources-drawer.entry.js +1 -1
  188. package/dist/esm/bs-chatbot-suggestion-button.entry.js +1 -1
  189. package/dist/esm/bs-checkbox-skeleton.entry.js +1 -1
  190. package/dist/esm/bs-datepicker.entry.js +408 -0
  191. package/dist/esm/bs-file-upload-item.entry.js +1 -1
  192. package/dist/esm/bs-file-upload.entry.js +1 -1
  193. package/dist/esm/bs-icon-button.entry.js +1 -1
  194. package/dist/esm/bs-inline-tab.entry.js +1 -1
  195. package/dist/esm/{bs-input.entry.js → bs-input_2.entry.js} +37 -5
  196. package/dist/esm/bs-menu.entry.js +1 -1
  197. package/dist/esm/bs-navigation-drawer-item.entry.js +1 -1
  198. package/dist/esm/bs-navigation-drawer.entry.js +2 -2
  199. package/dist/esm/bs-navigation-header.entry.js +1 -1
  200. package/dist/esm/bs-pagination.entry.js +1 -1
  201. package/dist/esm/bs-progress-linear.entry.js +2 -2
  202. package/dist/esm/bs-progress.entry.js +2 -2
  203. package/dist/esm/bs-radio.entry.js +1 -1
  204. package/dist/esm/bs-slider.entry.js +1 -1
  205. package/dist/esm/bs-snackbar.entry.js +1 -1
  206. package/dist/esm/bs-source-link.entry.js +2 -2
  207. package/dist/esm/bs-stepper-step.entry.js +1 -1
  208. package/dist/esm/bs-stepper.entry.js +1 -1
  209. package/dist/esm/bs-switch.entry.js +1 -1
  210. package/dist/esm/bs-tab.entry.js +1 -1
  211. package/dist/esm/bs-tabs.entry.js +1 -1
  212. package/dist/esm/bs-timepicker.entry.js +207 -0
  213. package/dist/esm/bs-toast.entry.js +1 -1
  214. package/dist/esm/bs-tooltip.entry.js +1 -1
  215. package/dist/esm/loader.js +1 -1
  216. package/dist/types/components/bs-datepicker/bs-datepicker.cmp.test.d.ts +1 -0
  217. package/dist/types/components/bs-datepicker/bs-datepicker.d.ts +136 -0
  218. package/dist/types/components/bs-datepicker/bs-datepicker.stories.d.ts +20 -0
  219. package/dist/types/components/bs-timepicker/bs-timepicker.cmp.test.d.ts +1 -0
  220. package/dist/types/components/bs-timepicker/bs-timepicker.d.ts +101 -0
  221. package/dist/types/components/bs-timepicker/bs-timepicker.stories.d.ts +14 -0
  222. package/dist/types/components.d.ts +515 -0
  223. package/package.json +1 -1
  224. package/dist/brandsync-wc/p-7b00dd36.entry.js +0 -1
  225. package/dist/brandsync-wc/p-ae978c9a.entry.js +0 -1
  226. package/dist/brandsync-wc/p-c10d2529.entry.js +0 -1
  227. package/dist/cjs/bs-menu-item.cjs.entry.js +0 -34
  228. package/dist/components/p-Buly0d5G.js +0 -1
  229. package/dist/esm/bs-menu-item.entry.js +0 -32
@@ -0,0 +1,782 @@
1
+ import { h } from "@stencil/core";
2
+ /**
3
+ * An inline calendar for picking a single date, or a start/end date range. Matches the Figma
4
+ * "Date picker" component's two types: "Default" (month and year dropdowns above the grid) and
5
+ * "Range" (start and end date fields above the grid, with the days between highlighted).
6
+ *
7
+ * Dates are always `YYYY-MM-DD` strings, interpreted in the user's local time zone -- never full
8
+ * ISO timestamps -- so a date can't shift by a day across time zones.
9
+ *
10
+ * The calendar renders inline at a fixed width; to show it as a popover, put it inside a
11
+ * `bs-menu` or your own overlay.
12
+ *
13
+ * ## When to use
14
+ * - Picking a date where seeing the surrounding days of the week/month helps (a booking, a
15
+ * deadline, a report window).
16
+ * - Picking a period (`range`) such as a start and end date.
17
+ *
18
+ * ## When not to use
19
+ * - A date the user knows by heart and can type quickly (a birth date) -- `bs-input type="date"`
20
+ * is faster there.
21
+ *
22
+ * ## Keyboard
23
+ * Arrow keys move by day/week, Home/End jump to the start/end of the week, PageUp/PageDown move by
24
+ * month (with Shift, by year), Enter/Space select the focused day.
25
+ *
26
+ * @part container - The outer card.
27
+ * @part header - The row of month/year dropdowns (default) or start/end fields (range).
28
+ * @part menu - The month/year dropdown list, when open (default mode).
29
+ * @part nav - The row holding the previous/next buttons and the title.
30
+ * @part prev - The previous-month button.
31
+ * @part next - The next-month button.
32
+ * @part title - The title between the nav buttons.
33
+ * @part weekday - Each weekday column header.
34
+ * @part grid - The day grid.
35
+ * @part day - Each day button.
36
+ * @part selected - A selected day (the single date, or either end of a range), in addition to `day`.
37
+ * @part in-range - A day strictly between the range start and end, in addition to `day`.
38
+ * @part outside - A day from the previous/next month, in addition to `day`.
39
+ * @part today - Today's day button, in addition to `day`.
40
+ */
41
+ export class BsDatepicker {
42
+ el;
43
+ internals;
44
+ initialValue = '';
45
+ initialStart = '';
46
+ initialEnd = '';
47
+ /** The `name` the value is submitted under in a surrounding `<form>`. In `range` mode the dates
48
+ * are submitted as `<name>-start` and `<name>-end`. */
49
+ name;
50
+ /** Select a start/end range instead of a single date. */
51
+ range = false;
52
+ /** The selected date (`YYYY-MM-DD`) in single mode. Mutable so a click updates it directly;
53
+ * `bsChange` still fires for the consumer to react. Ignored when `range` is set. */
54
+ value = '';
55
+ /** The range start (`YYYY-MM-DD`) in `range` mode. */
56
+ start = '';
57
+ /** The range end (`YYYY-MM-DD`) in `range` mode. */
58
+ end = '';
59
+ /** Earliest selectable date (`YYYY-MM-DD`). Earlier days render disabled. */
60
+ min;
61
+ /** Latest selectable date (`YYYY-MM-DD`). Later days render disabled. */
62
+ max;
63
+ /** BCP 47 locale used for month names, weekday names and the title. */
64
+ locale = 'en-GB';
65
+ /** First column of the grid: `0` for Sunday (the Figma spec), `1` for Monday, ... `6`. */
66
+ firstDayOfWeek = 0;
67
+ /** Label above the start field in `range` mode. */
68
+ startLabel = 'Start date';
69
+ /** Label above the end field in `range` mode. */
70
+ endLabel = 'End date';
71
+ /** Accessible name for the month dropdown (single mode). */
72
+ monthLabel = 'Month';
73
+ /** Accessible name for the year dropdown (single mode). */
74
+ yearLabel = 'Year';
75
+ /** Accessible name for the previous-month button. */
76
+ previousLabel = 'Previous month';
77
+ /** Accessible name for the next-month button. */
78
+ nextLabel = 'Next month';
79
+ /** Fires when the user changes the selection. Single mode: `{ value }`. Range mode: `{ start,
80
+ * end }` -- fired once for the first click (with an empty `end`) and again when the range is
81
+ * completed. Not fired when the props are set programmatically. */
82
+ bsChange;
83
+ /** First day of the month currently displayed. */
84
+ viewDate = firstOfMonth(new Date());
85
+ /** The day holding the roving tabindex. */
86
+ focusedIso = '';
87
+ /** The day the pointer is over while a range is half-picked, for the live range preview. */
88
+ hoverIso = '';
89
+ /** Text the user is typing into a range field, keyed by which field. Cleared on commit. */
90
+ draft = {};
91
+ /** Which header dropdown (single mode) is open. */
92
+ openMenu = null;
93
+ shouldFocusDay = false;
94
+ menuToScroll = false;
95
+ componentWillLoad() {
96
+ this.initialValue = this.value;
97
+ this.initialStart = this.start;
98
+ this.initialEnd = this.end;
99
+ this.showSelection();
100
+ this.syncFormValue();
101
+ }
102
+ componentDidRender() {
103
+ if (this.menuToScroll) {
104
+ this.menuToScroll = false;
105
+ // Centre the current month/year in the list. Done by hand rather than scrollIntoView, which
106
+ // would also scroll the page.
107
+ const menu = this.el.shadowRoot.querySelector('.bs-datepicker__menu');
108
+ const current = menu?.querySelector('[data-current]');
109
+ if (menu && current)
110
+ menu.scrollTop = current.offsetTop - menu.clientHeight / 2 + current.offsetHeight / 2;
111
+ }
112
+ if (!this.shouldFocusDay)
113
+ return;
114
+ this.shouldFocusDay = false;
115
+ const day = this.el.shadowRoot.querySelector(`[data-date="${this.focusedIso}"]`);
116
+ day?.focus();
117
+ }
118
+ onSelectionChange() {
119
+ this.syncFormValue();
120
+ }
121
+ onSelectionJump() {
122
+ // A programmatic change should bring the new selection into view.
123
+ this.showSelection();
124
+ }
125
+ /** Called by the browser when the surrounding `<form>` is reset. */
126
+ formResetCallback() {
127
+ this.value = this.initialValue;
128
+ this.start = this.initialStart;
129
+ this.end = this.initialEnd;
130
+ this.draft = {};
131
+ }
132
+ showSelection() {
133
+ const anchor = parseIso(this.range ? this.start : this.value);
134
+ if (anchor)
135
+ this.viewDate = firstOfMonth(anchor);
136
+ }
137
+ syncFormValue() {
138
+ if (!this.internals?.setFormValue)
139
+ return;
140
+ if (this.range) {
141
+ if (!this.name) {
142
+ this.internals.setFormValue(null);
143
+ return;
144
+ }
145
+ const data = new FormData();
146
+ data.append(`${this.name}-start`, this.start ?? '');
147
+ data.append(`${this.name}-end`, this.end ?? '');
148
+ this.internals.setFormValue(data);
149
+ }
150
+ else {
151
+ this.internals.setFormValue(this.value ?? '');
152
+ }
153
+ }
154
+ // --- selection ---------------------------------------------------------------------------
155
+ isDisabled(d) {
156
+ const min = parseIso(this.min);
157
+ const max = parseIso(this.max);
158
+ return (!!min && d < min) || (!!max && d > max);
159
+ }
160
+ selectDay(d) {
161
+ if (this.isDisabled(d))
162
+ return;
163
+ const iso = toIso(d);
164
+ if (d.getMonth() !== this.viewDate.getMonth() || d.getFullYear() !== this.viewDate.getFullYear()) {
165
+ this.viewDate = firstOfMonth(d);
166
+ }
167
+ this.focusedIso = iso;
168
+ if (!this.range) {
169
+ this.value = iso;
170
+ this.bsChange.emit({ value: iso });
171
+ return;
172
+ }
173
+ // First click, or a click after a completed range, starts a new range. A click before the
174
+ // current start restarts from there rather than producing a backwards range.
175
+ if (!this.start || this.end || iso < this.start) {
176
+ this.start = iso;
177
+ this.end = '';
178
+ }
179
+ else {
180
+ this.end = iso;
181
+ }
182
+ this.hoverIso = '';
183
+ this.draft = {};
184
+ this.bsChange.emit({ start: this.start, end: this.end });
185
+ }
186
+ commitDraft(field) {
187
+ const text = this.draft[field];
188
+ if (text === undefined)
189
+ return;
190
+ const d = parseIso(text);
191
+ const next = { ...this.draft };
192
+ delete next[field];
193
+ this.draft = next;
194
+ if (!d || this.isDisabled(d))
195
+ return; // invalid text: fall back to the committed value
196
+ let start = field === 'start' ? toIso(d) : this.start;
197
+ let end = field === 'end' ? toIso(d) : this.end;
198
+ if (start && end && end < start) {
199
+ if (field === 'start')
200
+ end = '';
201
+ else
202
+ start = '';
203
+ }
204
+ this.start = start;
205
+ this.end = end;
206
+ this.showSelection();
207
+ this.bsChange.emit({ start, end });
208
+ }
209
+ // --- navigation --------------------------------------------------------------------------
210
+ moveView(months) {
211
+ const v = this.viewDate;
212
+ this.viewDate = new Date(v.getFullYear(), v.getMonth() + months, 1);
213
+ }
214
+ onKeyDown = (ev, current) => {
215
+ const step = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 };
216
+ let next;
217
+ if (ev.key in step) {
218
+ next = addDays(current, step[ev.key]);
219
+ }
220
+ else if (ev.key === 'Home' || ev.key === 'End') {
221
+ const col = (current.getDay() - this.safeFirstDay + 7) % 7;
222
+ next = addDays(current, ev.key === 'Home' ? -col : 6 - col);
223
+ }
224
+ else if (ev.key === 'PageUp' || ev.key === 'PageDown') {
225
+ const dir = ev.key === 'PageUp' ? -1 : 1;
226
+ next = addMonths(current, ev.shiftKey ? dir * 12 : dir);
227
+ }
228
+ else {
229
+ return;
230
+ }
231
+ ev.preventDefault();
232
+ this.focusedIso = toIso(next);
233
+ this.viewDate = firstOfMonth(next);
234
+ this.shouldFocusDay = true;
235
+ };
236
+ get safeFirstDay() {
237
+ const n = Math.trunc(Number(this.firstDayOfWeek));
238
+ return Number.isFinite(n) ? ((n % 7) + 7) % 7 : 0;
239
+ }
240
+ // --- rendering ---------------------------------------------------------------------------
241
+ get fmt() {
242
+ const locale = this.locale || 'en-GB';
243
+ try {
244
+ Intl.DateTimeFormat.supportedLocalesOf(locale);
245
+ return locale;
246
+ }
247
+ catch {
248
+ return 'en-GB';
249
+ }
250
+ }
251
+ formatField(iso) {
252
+ const d = parseIso(iso);
253
+ return d ? new Intl.DateTimeFormat(this.fmt, { day: 'numeric', month: 'short', year: 'numeric' }).format(d) : '';
254
+ }
255
+ titleText() {
256
+ const selected = !this.range ? parseIso(this.value) : undefined;
257
+ if (selected) {
258
+ return new Intl.DateTimeFormat(this.fmt, { day: 'numeric', month: 'long', year: 'numeric' }).format(selected);
259
+ }
260
+ return new Intl.DateTimeFormat(this.fmt, { month: 'long', year: 'numeric' }).format(this.viewDate);
261
+ }
262
+ monthOptions() {
263
+ const f = new Intl.DateTimeFormat(this.fmt, { month: 'long' });
264
+ return Array.from({ length: 12 }, (_, m) => ({ label: f.format(new Date(2000, m, 1)), value: String(m) }));
265
+ }
266
+ yearOptions() {
267
+ const current = this.viewDate.getFullYear();
268
+ const min = parseIso(this.min)?.getFullYear() ?? current - 100;
269
+ const max = parseIso(this.max)?.getFullYear() ?? current + 100;
270
+ const options = [];
271
+ for (let y = Math.min(min, current); y <= Math.max(max, current); y++) {
272
+ options.push({ label: String(y), value: String(y) });
273
+ }
274
+ return options;
275
+ }
276
+ weekdays() {
277
+ const f = new Intl.DateTimeFormat(this.fmt, { weekday: 'short' });
278
+ // 2023-01-01 was a Sunday.
279
+ return Array.from({ length: 7 }, (_, i) => f.format(new Date(2023, 0, 1 + ((this.safeFirstDay + i) % 7))));
280
+ }
281
+ gridDays() {
282
+ const first = this.viewDate;
283
+ const lead = (first.getDay() - this.safeFirstDay + 7) % 7;
284
+ const gridStart = addDays(first, -lead);
285
+ // Always 6 rows, so the card doesn't change height from month to month (as in the Figma).
286
+ return Array.from({ length: 42 }, (_, i) => addDays(gridStart, i));
287
+ }
288
+ renderHeader() {
289
+ if (this.range) {
290
+ const field = (which, label) => (h("bs-input", { label: label, placeholder: "YYYY-MM-DD", value: this.draft[which] ?? this.formatField(this[which]), onBsInput: (ev) => (this.draft = { ...this.draft, [which]: ev.detail }), onBsChange: () => this.commitDraft(which), onFocusin: () => {
291
+ // Typing is ISO: swap the pretty "12 Sept, 2026" for something parseable on focus.
292
+ if (this.draft[which] === undefined)
293
+ this.draft = { ...this.draft, [which]: this[which] };
294
+ }, onFocusout: () => this.commitDraft(which) }));
295
+ return (h("div", { part: "header", class: "bs-datepicker__header bs-datepicker__header--range" }, field('start', this.startLabel), field('end', this.endLabel)));
296
+ }
297
+ return (h("div", { part: "header", class: "bs-datepicker__header" }, this.renderDropdown('month', this.monthLabel, this.monthOptions(), String(this.viewDate.getMonth()), (value) => (this.viewDate = new Date(this.viewDate.getFullYear(), Number(value), 1))), this.renderDropdown('year', this.yearLabel, this.yearOptions(), String(this.viewDate.getFullYear()), (value) => (this.viewDate = new Date(Number(value), this.viewDate.getMonth(), 1)))));
298
+ }
299
+ /** A `bs-input type="dropdown"` trigger with our own `bs-menu` list below it. bs-input's built-in
300
+ * menu has no checkmark or scroll limit, so it's used only as the field look: it gets no
301
+ * `options` (so renders no menu of its own) and its `bsOpen` toggles ours. */
302
+ renderDropdown(which, label, options, current, onPick) {
303
+ const open = this.openMenu === which;
304
+ const close = () => {
305
+ this.openMenu = null;
306
+ };
307
+ return (h("div", { class: "bs-datepicker__dropdown", onKeyDown: (ev) => {
308
+ if (ev.key !== 'Escape' || !open)
309
+ return;
310
+ close();
311
+ ev.currentTarget.querySelector('bs-input')?.focus();
312
+ }, onFocusout: (ev) => {
313
+ const related = ev.relatedTarget;
314
+ if (open && (!related || !ev.currentTarget.contains(related)))
315
+ close();
316
+ } }, h("bs-input", { type: "dropdown", class: "bs-datepicker__select", label: label, value: options.find(o => o.value === current)?.label ?? '', open: open, onBsOpen: () => {
317
+ this.menuToScroll = !open;
318
+ this.openMenu = open ? null : which;
319
+ } }), open && (h("bs-menu", { part: "menu", class: "bs-datepicker__menu", role: "listbox" }, options.map(o => (h("bs-menu-item", { key: o.value, "data-current": o.value === current ? '' : undefined, "aria-current": o.value === current ? 'true' : undefined, onBsSelect: () => {
320
+ onPick(o.value);
321
+ close();
322
+ this.el.shadowRoot.querySelector(`.bs-datepicker__dropdown bs-input[label="${label}"]`)?.focus();
323
+ } }, h("span", { class: "bs-datepicker__option" }, h("span", null, o.label), o.value === current && (h("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true" }, h("path", { d: "M5 12.5L10 17.5L19 7.5", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" })))))))))));
324
+ }
325
+ render() {
326
+ const days = this.gridDays();
327
+ const todayIso = toIso(new Date());
328
+ const selectedStart = this.range ? this.start : this.value;
329
+ const selectedEnd = this.range ? this.end : '';
330
+ // While the range is half-picked, preview it up to the hovered day.
331
+ const previewEnd = this.range && this.start && !this.end && this.hoverIso > this.start ? this.hoverIso : selectedEnd;
332
+ const tabbable = days.some(d => toIso(d) === this.focusedIso && d.getMonth() === this.viewDate.getMonth())
333
+ ? this.focusedIso
334
+ : this.defaultTabbable(days);
335
+ const isInRange = (iso) => !!selectedStart && !!previewEnd && iso > selectedStart && iso < previewEnd;
336
+ const weekdays = this.weekdays();
337
+ return (h("div", { key: '49e2ce73c32ee98eb2c8276fb23b159392b9292a', part: "container", class: "bs-datepicker" }, this.renderHeader(), h("div", { key: 'da69881edff77ee3584b4565a4b39024ce2cd4f7', part: "nav", class: "bs-datepicker__nav" }, h("button", { key: 'f96dea3cc2821bf757afcee158c092deefe45b8b', part: "prev", type: "button", class: "bs-datepicker__nav-button", "aria-label": this.previousLabel, onClick: () => this.moveView(-1) }, h("svg", { key: '7be3e0ca1588852357d13ade50f594633f86a56a', viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true" }, h("path", { key: '513165ad97411656af1742376cf7d75eda544814', d: "M15 18L9 12L15 6", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }))), h("div", { key: 'bc55234eb1bd053c87388e7d6ebe31049f903cea', part: "title", class: "bs-datepicker__title", "aria-live": "polite" }, this.titleText()), h("button", { key: '2436e91d78710f7d0716553660c8e1fff2e7d2da', part: "next", type: "button", class: "bs-datepicker__nav-button", "aria-label": this.nextLabel, onClick: () => this.moveView(1) }, h("svg", { key: '47f183221234d91d736f45207e84b14ee57b469f', viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true" }, h("path", { key: 'bd4abceed66ef781fab224646d371b648d3c0d1d', d: "M9 18L15 12L9 6", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" })))), h("div", { key: 'e669ad28eb8461dcf5a24191dca379ab3cbc0111', part: "grid", class: "bs-datepicker__grid", role: "grid", "aria-label": this.titleText() }, h("div", { key: '440719175dd4f4a745b9de22126029633bfe91a3', class: "bs-datepicker__row", role: "row" }, weekdays.map(w => (h("div", { part: "weekday", class: "bs-datepicker__weekday", role: "columnheader" }, w)))), Array.from({ length: 6 }, (_, r) => {
338
+ const row = days.slice(r * 7, r * 7 + 7);
339
+ return (h("div", { class: "bs-datepicker__row", role: "row" }, row.map((d, c) => {
340
+ const iso = toIso(d);
341
+ const outside = d.getMonth() !== this.viewDate.getMonth();
342
+ const isStart = iso === selectedStart;
343
+ const isEnd = !!selectedEnd && iso === selectedEnd;
344
+ const selected = isStart || isEnd;
345
+ const inRange = isInRange(iso);
346
+ // Figma: the band covers only the days between the two ends, rounded where a run
347
+ // starts/ends (also at a week boundary), with the end days sitting outside it.
348
+ const classes = {
349
+ 'bs-datepicker__cell': true,
350
+ 'bs-datepicker__cell--in-range': inRange,
351
+ 'bs-datepicker__cell--band-start': inRange && !(c > 0 && isInRange(toIso(row[c - 1]))),
352
+ 'bs-datepicker__cell--band-end': inRange && !(c < 6 && isInRange(toIso(row[c + 1]))),
353
+ };
354
+ const parts = ['day', selected && 'selected', inRange && 'in-range', outside && 'outside', iso === todayIso && 'today']
355
+ .filter(Boolean)
356
+ .join(' ');
357
+ return (h("div", { class: classes, role: "gridcell", "aria-selected": selected || inRange ? 'true' : 'false' }, h("button", { part: parts, type: "button", class: {
358
+ 'bs-datepicker__day': true,
359
+ 'bs-datepicker__day--selected': selected,
360
+ 'bs-datepicker__day--in-range': inRange,
361
+ 'bs-datepicker__day--outside': outside,
362
+ 'bs-datepicker__day--today': iso === todayIso,
363
+ }, "data-date": iso, tabindex: iso === tabbable ? 0 : -1, disabled: this.isDisabled(d), "aria-current": iso === todayIso ? 'date' : undefined, "aria-label": new Intl.DateTimeFormat(this.fmt, { weekday: 'long', day: '2-digit', month: 'long', year: 'numeric' }).format(d), onClick: () => this.selectDay(d), onKeyDown: ev => this.onKeyDown(ev, d), onMouseEnter: () => {
364
+ if (this.range && this.start && !this.end)
365
+ this.hoverIso = iso;
366
+ } }, String(d.getDate()).padStart(2, '0'))));
367
+ })));
368
+ }))));
369
+ }
370
+ /** The day that should be reachable with Tab when nothing in view has been focused yet: the
371
+ * selection if it's in the displayed month, else today if it is, else the 1st. */
372
+ defaultTabbable(days) {
373
+ const inView = (iso) => days.some(d => toIso(d) === iso && d.getMonth() === this.viewDate.getMonth());
374
+ const selected = this.range ? this.start : this.value;
375
+ if (selected && inView(selected))
376
+ return selected;
377
+ const today = toIso(new Date());
378
+ if (inView(today))
379
+ return today;
380
+ return toIso(this.viewDate);
381
+ }
382
+ static get is() { return "bs-datepicker"; }
383
+ static get encapsulation() { return "shadow"; }
384
+ static get formAssociated() { return true; }
385
+ static get originalStyleUrls() {
386
+ return {
387
+ "$": ["bs-datepicker.css"]
388
+ };
389
+ }
390
+ static get styleUrls() {
391
+ return {
392
+ "$": ["bs-datepicker.css"]
393
+ };
394
+ }
395
+ static get properties() {
396
+ return {
397
+ "name": {
398
+ "type": "string",
399
+ "mutable": false,
400
+ "complexType": {
401
+ "original": "string",
402
+ "resolved": "string",
403
+ "references": {}
404
+ },
405
+ "required": false,
406
+ "optional": true,
407
+ "docs": {
408
+ "tags": [],
409
+ "text": "The `name` the value is submitted under in a surrounding `<form>`. In `range` mode the dates\nare submitted as `<name>-start` and `<name>-end`."
410
+ },
411
+ "getter": false,
412
+ "setter": false,
413
+ "reflect": true,
414
+ "attribute": "name"
415
+ },
416
+ "range": {
417
+ "type": "boolean",
418
+ "mutable": false,
419
+ "complexType": {
420
+ "original": "boolean",
421
+ "resolved": "boolean",
422
+ "references": {}
423
+ },
424
+ "required": false,
425
+ "optional": false,
426
+ "docs": {
427
+ "tags": [],
428
+ "text": "Select a start/end range instead of a single date."
429
+ },
430
+ "getter": false,
431
+ "setter": false,
432
+ "reflect": true,
433
+ "attribute": "range",
434
+ "defaultValue": "false"
435
+ },
436
+ "value": {
437
+ "type": "string",
438
+ "mutable": true,
439
+ "complexType": {
440
+ "original": "string",
441
+ "resolved": "string",
442
+ "references": {}
443
+ },
444
+ "required": false,
445
+ "optional": false,
446
+ "docs": {
447
+ "tags": [],
448
+ "text": "The selected date (`YYYY-MM-DD`) in single mode. Mutable so a click updates it directly;\n`bsChange` still fires for the consumer to react. Ignored when `range` is set."
449
+ },
450
+ "getter": false,
451
+ "setter": false,
452
+ "reflect": true,
453
+ "attribute": "value",
454
+ "defaultValue": "''"
455
+ },
456
+ "start": {
457
+ "type": "string",
458
+ "mutable": true,
459
+ "complexType": {
460
+ "original": "string",
461
+ "resolved": "string",
462
+ "references": {}
463
+ },
464
+ "required": false,
465
+ "optional": false,
466
+ "docs": {
467
+ "tags": [],
468
+ "text": "The range start (`YYYY-MM-DD`) in `range` mode."
469
+ },
470
+ "getter": false,
471
+ "setter": false,
472
+ "reflect": true,
473
+ "attribute": "start",
474
+ "defaultValue": "''"
475
+ },
476
+ "end": {
477
+ "type": "string",
478
+ "mutable": true,
479
+ "complexType": {
480
+ "original": "string",
481
+ "resolved": "string",
482
+ "references": {}
483
+ },
484
+ "required": false,
485
+ "optional": false,
486
+ "docs": {
487
+ "tags": [],
488
+ "text": "The range end (`YYYY-MM-DD`) in `range` mode."
489
+ },
490
+ "getter": false,
491
+ "setter": false,
492
+ "reflect": true,
493
+ "attribute": "end",
494
+ "defaultValue": "''"
495
+ },
496
+ "min": {
497
+ "type": "string",
498
+ "mutable": false,
499
+ "complexType": {
500
+ "original": "string",
501
+ "resolved": "string",
502
+ "references": {}
503
+ },
504
+ "required": false,
505
+ "optional": true,
506
+ "docs": {
507
+ "tags": [],
508
+ "text": "Earliest selectable date (`YYYY-MM-DD`). Earlier days render disabled."
509
+ },
510
+ "getter": false,
511
+ "setter": false,
512
+ "reflect": false,
513
+ "attribute": "min"
514
+ },
515
+ "max": {
516
+ "type": "string",
517
+ "mutable": false,
518
+ "complexType": {
519
+ "original": "string",
520
+ "resolved": "string",
521
+ "references": {}
522
+ },
523
+ "required": false,
524
+ "optional": true,
525
+ "docs": {
526
+ "tags": [],
527
+ "text": "Latest selectable date (`YYYY-MM-DD`). Later days render disabled."
528
+ },
529
+ "getter": false,
530
+ "setter": false,
531
+ "reflect": false,
532
+ "attribute": "max"
533
+ },
534
+ "locale": {
535
+ "type": "string",
536
+ "mutable": false,
537
+ "complexType": {
538
+ "original": "string",
539
+ "resolved": "string",
540
+ "references": {}
541
+ },
542
+ "required": false,
543
+ "optional": false,
544
+ "docs": {
545
+ "tags": [],
546
+ "text": "BCP 47 locale used for month names, weekday names and the title."
547
+ },
548
+ "getter": false,
549
+ "setter": false,
550
+ "reflect": false,
551
+ "attribute": "locale",
552
+ "defaultValue": "'en-GB'"
553
+ },
554
+ "firstDayOfWeek": {
555
+ "type": "number",
556
+ "mutable": false,
557
+ "complexType": {
558
+ "original": "number",
559
+ "resolved": "number",
560
+ "references": {}
561
+ },
562
+ "required": false,
563
+ "optional": false,
564
+ "docs": {
565
+ "tags": [],
566
+ "text": "First column of the grid: `0` for Sunday (the Figma spec), `1` for Monday, ... `6`."
567
+ },
568
+ "getter": false,
569
+ "setter": false,
570
+ "reflect": false,
571
+ "attribute": "first-day-of-week",
572
+ "defaultValue": "0"
573
+ },
574
+ "startLabel": {
575
+ "type": "string",
576
+ "mutable": false,
577
+ "complexType": {
578
+ "original": "string",
579
+ "resolved": "string",
580
+ "references": {}
581
+ },
582
+ "required": false,
583
+ "optional": false,
584
+ "docs": {
585
+ "tags": [],
586
+ "text": "Label above the start field in `range` mode."
587
+ },
588
+ "getter": false,
589
+ "setter": false,
590
+ "reflect": false,
591
+ "attribute": "start-label",
592
+ "defaultValue": "'Start date'"
593
+ },
594
+ "endLabel": {
595
+ "type": "string",
596
+ "mutable": false,
597
+ "complexType": {
598
+ "original": "string",
599
+ "resolved": "string",
600
+ "references": {}
601
+ },
602
+ "required": false,
603
+ "optional": false,
604
+ "docs": {
605
+ "tags": [],
606
+ "text": "Label above the end field in `range` mode."
607
+ },
608
+ "getter": false,
609
+ "setter": false,
610
+ "reflect": false,
611
+ "attribute": "end-label",
612
+ "defaultValue": "'End date'"
613
+ },
614
+ "monthLabel": {
615
+ "type": "string",
616
+ "mutable": false,
617
+ "complexType": {
618
+ "original": "string",
619
+ "resolved": "string",
620
+ "references": {}
621
+ },
622
+ "required": false,
623
+ "optional": false,
624
+ "docs": {
625
+ "tags": [],
626
+ "text": "Accessible name for the month dropdown (single mode)."
627
+ },
628
+ "getter": false,
629
+ "setter": false,
630
+ "reflect": false,
631
+ "attribute": "month-label",
632
+ "defaultValue": "'Month'"
633
+ },
634
+ "yearLabel": {
635
+ "type": "string",
636
+ "mutable": false,
637
+ "complexType": {
638
+ "original": "string",
639
+ "resolved": "string",
640
+ "references": {}
641
+ },
642
+ "required": false,
643
+ "optional": false,
644
+ "docs": {
645
+ "tags": [],
646
+ "text": "Accessible name for the year dropdown (single mode)."
647
+ },
648
+ "getter": false,
649
+ "setter": false,
650
+ "reflect": false,
651
+ "attribute": "year-label",
652
+ "defaultValue": "'Year'"
653
+ },
654
+ "previousLabel": {
655
+ "type": "string",
656
+ "mutable": false,
657
+ "complexType": {
658
+ "original": "string",
659
+ "resolved": "string",
660
+ "references": {}
661
+ },
662
+ "required": false,
663
+ "optional": false,
664
+ "docs": {
665
+ "tags": [],
666
+ "text": "Accessible name for the previous-month button."
667
+ },
668
+ "getter": false,
669
+ "setter": false,
670
+ "reflect": false,
671
+ "attribute": "previous-label",
672
+ "defaultValue": "'Previous month'"
673
+ },
674
+ "nextLabel": {
675
+ "type": "string",
676
+ "mutable": false,
677
+ "complexType": {
678
+ "original": "string",
679
+ "resolved": "string",
680
+ "references": {}
681
+ },
682
+ "required": false,
683
+ "optional": false,
684
+ "docs": {
685
+ "tags": [],
686
+ "text": "Accessible name for the next-month button."
687
+ },
688
+ "getter": false,
689
+ "setter": false,
690
+ "reflect": false,
691
+ "attribute": "next-label",
692
+ "defaultValue": "'Next month'"
693
+ }
694
+ };
695
+ }
696
+ static get states() {
697
+ return {
698
+ "viewDate": {},
699
+ "focusedIso": {},
700
+ "hoverIso": {},
701
+ "draft": {},
702
+ "openMenu": {}
703
+ };
704
+ }
705
+ static get events() {
706
+ return [{
707
+ "method": "bsChange",
708
+ "name": "bsChange",
709
+ "bubbles": true,
710
+ "cancelable": true,
711
+ "composed": true,
712
+ "docs": {
713
+ "tags": [],
714
+ "text": "Fires when the user changes the selection. Single mode: `{ value }`. Range mode: `{ start,\nend }` -- fired once for the first click (with an empty `end`) and again when the range is\ncompleted. Not fired when the props are set programmatically."
715
+ },
716
+ "complexType": {
717
+ "original": "BsDatepickerChange",
718
+ "resolved": "BsDatepickerChange",
719
+ "references": {
720
+ "BsDatepickerChange": {
721
+ "location": "local",
722
+ "path": "/home/runner/work/eg-brandsync-storybook/eg-brandsync-storybook/packages/wc/src/components/bs-datepicker/bs-datepicker.tsx",
723
+ "id": "src/components/bs-datepicker/bs-datepicker.tsx::BsDatepickerChange"
724
+ }
725
+ }
726
+ }
727
+ }];
728
+ }
729
+ static get elementRef() { return "el"; }
730
+ static get watchers() {
731
+ return [{
732
+ "propName": "value",
733
+ "methodName": "onSelectionChange"
734
+ }, {
735
+ "propName": "start",
736
+ "methodName": "onSelectionChange"
737
+ }, {
738
+ "propName": "end",
739
+ "methodName": "onSelectionChange"
740
+ }, {
741
+ "propName": "range",
742
+ "methodName": "onSelectionChange"
743
+ }, {
744
+ "propName": "name",
745
+ "methodName": "onSelectionChange"
746
+ }, {
747
+ "propName": "value",
748
+ "methodName": "onSelectionJump"
749
+ }, {
750
+ "propName": "start",
751
+ "methodName": "onSelectionJump"
752
+ }];
753
+ }
754
+ static get attachInternalsMemberName() { return "internals"; }
755
+ }
756
+ // --- date helpers (local time; `YYYY-MM-DD` strings) ---------------------------------------
757
+ function pad(n) {
758
+ return String(n).padStart(2, '0');
759
+ }
760
+ function toIso(d) {
761
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
762
+ }
763
+ function parseIso(s) {
764
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec((s ?? '').trim());
765
+ if (!m)
766
+ return undefined;
767
+ const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
768
+ // Reject overflow such as 2026-02-31, which `Date` silently rolls into March.
769
+ return toIso(d) === `${m[1]}-${m[2]}-${m[3]}` ? d : undefined;
770
+ }
771
+ function firstOfMonth(d) {
772
+ return new Date(d.getFullYear(), d.getMonth(), 1);
773
+ }
774
+ function addDays(d, n) {
775
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
776
+ }
777
+ function addMonths(d, n) {
778
+ // Clamp so Jan 31 + 1 month is Feb 28, not Mar 3.
779
+ const target = new Date(d.getFullYear(), d.getMonth() + n, 1);
780
+ const lastDay = new Date(target.getFullYear(), target.getMonth() + 1, 0).getDate();
781
+ return new Date(target.getFullYear(), target.getMonth(), Math.min(d.getDate(), lastDay));
782
+ }