snice 7.5.0 → 7.7.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 (265) hide show
  1. package/adapters/react/SniceProvider.js +1 -1
  2. package/adapters/react/SniceRouter.js +1 -1
  3. package/adapters/react/avatar.d.ts +1 -0
  4. package/adapters/react/avatar.d.ts.map +1 -1
  5. package/adapters/react/avatar.js +1 -1
  6. package/adapters/react/avatar.js.map +1 -1
  7. package/adapters/react/avatar.tsx +2 -1
  8. package/adapters/react/calendar.d.ts +4 -0
  9. package/adapters/react/calendar.d.ts.map +1 -1
  10. package/adapters/react/calendar.js +1 -1
  11. package/adapters/react/calendar.js.map +1 -1
  12. package/adapters/react/calendar.tsx +5 -1
  13. package/adapters/react/matchRoute.js +68 -2
  14. package/adapters/react/matchRoute.js.map +1 -1
  15. package/adapters/react/route-match.d.ts +7 -0
  16. package/adapters/react/useRequestHandler.js +1 -1
  17. package/bin/analyzer-contracts.js +60 -2
  18. package/bin/project-analyzer.js +1262 -118
  19. package/bin/snice.js +95 -5
  20. package/custom-elements.json +112 -0
  21. package/dist/cdn/accordion/snice-accordion.js +1 -1
  22. package/dist/cdn/action-bar/snice-action-bar.js +1 -1
  23. package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
  24. package/dist/cdn/alert/snice-alert.js +1 -1
  25. package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
  26. package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
  27. package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
  28. package/dist/cdn/availability/snice-availability.js +1 -1
  29. package/dist/cdn/avatar/README.md +1 -1
  30. package/dist/cdn/avatar/snice-avatar.js +9 -3
  31. package/dist/cdn/avatar/snice-avatar.js.map +1 -1
  32. package/dist/cdn/avatar/snice-avatar.min.js +2 -2
  33. package/dist/cdn/avatar/snice-avatar.min.js.map +1 -1
  34. package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
  35. package/dist/cdn/badge/snice-badge.js +1 -1
  36. package/dist/cdn/banner/snice-banner.js +1 -1
  37. package/dist/cdn/binpack/snice-binpack.js +1 -1
  38. package/dist/cdn/book/snice-book.js +1 -1
  39. package/dist/cdn/booking/snice-booking.js +1 -1
  40. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
  41. package/dist/cdn/button/snice-button.js +2 -2
  42. package/dist/cdn/button/snice-button.js.map +1 -1
  43. package/dist/cdn/button/snice-button.min.js +1 -1
  44. package/dist/cdn/button/snice-button.min.js.map +1 -1
  45. package/dist/cdn/calendar/README.md +2 -2
  46. package/dist/cdn/calendar/snice-calendar.js +562 -40
  47. package/dist/cdn/calendar/snice-calendar.js.map +1 -1
  48. package/dist/cdn/calendar/snice-calendar.min.js +28 -1
  49. package/dist/cdn/calendar/snice-calendar.min.js.map +1 -1
  50. package/dist/cdn/camera/snice-camera.js +1 -1
  51. package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
  52. package/dist/cdn/candlestick/snice-candlestick.js +1 -1
  53. package/dist/cdn/card/snice-card.js +1 -1
  54. package/dist/cdn/carousel/snice-carousel.js +1 -1
  55. package/dist/cdn/cart/snice-cart.js +1 -1
  56. package/dist/cdn/chart/snice-chart.js +1 -1
  57. package/dist/cdn/chat/snice-chat.js +1 -1
  58. package/dist/cdn/checkbox/snice-checkbox.js +1 -1
  59. package/dist/cdn/chip/snice-chip.js +1 -1
  60. package/dist/cdn/code-block/snice-code-block.js +1 -1
  61. package/dist/cdn/color-display/snice-color-display.js +1 -1
  62. package/dist/cdn/color-picker/snice-color-picker.js +1 -1
  63. package/dist/cdn/command-palette/snice-command-palette.js +1 -1
  64. package/dist/cdn/comments/snice-comments.js +1 -1
  65. package/dist/cdn/countdown/snice-countdown.js +1 -1
  66. package/dist/cdn/cropper/snice-cropper.js +1 -1
  67. package/dist/cdn/data-card/snice-data-card.js +1 -1
  68. package/dist/cdn/date-picker/snice-date-picker.js +1 -1
  69. package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
  70. package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
  71. package/dist/cdn/diff/snice-diff.js +1 -1
  72. package/dist/cdn/divider/snice-divider.js +1 -1
  73. package/dist/cdn/doc/snice-doc.js +1 -1
  74. package/dist/cdn/draw/snice-draw.js +1 -1
  75. package/dist/cdn/drawer/snice-drawer.js +1 -1
  76. package/dist/cdn/empty-state/snice-empty-state.js +1 -1
  77. package/dist/cdn/estimate/snice-estimate.js +1 -1
  78. package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
  79. package/dist/cdn/file-upload/snice-file-upload.js +1 -1
  80. package/dist/cdn/flip-card/snice-flip-card.js +1 -1
  81. package/dist/cdn/flow/snice-flow.js +1 -1
  82. package/dist/cdn/form-layout/snice-form-layout.js +1 -1
  83. package/dist/cdn/funnel/snice-funnel.js +1 -1
  84. package/dist/cdn/gantt/snice-gantt.js +1 -1
  85. package/dist/cdn/gauge/snice-gauge.js +1 -1
  86. package/dist/cdn/grid/snice-grid.js +1 -1
  87. package/dist/cdn/heatmap/snice-heatmap.js +1 -1
  88. package/dist/cdn/image/snice-image.js +1 -1
  89. package/dist/cdn/input/snice-input.js +1 -1
  90. package/dist/cdn/invoice/snice-invoice.js +1 -1
  91. package/dist/cdn/kanban/snice-kanban.js +1 -1
  92. package/dist/cdn/key-value/snice-key-value.js +1 -1
  93. package/dist/cdn/kpi/snice-kpi.js +1 -1
  94. package/dist/cdn/layout/snice-layout.js +1 -1
  95. package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
  96. package/dist/cdn/link/snice-link.js +1 -1
  97. package/dist/cdn/link-preview/snice-link-preview.js +1 -1
  98. package/dist/cdn/list/snice-list.js +1 -1
  99. package/dist/cdn/location/snice-location.js +1 -1
  100. package/dist/cdn/login/README.md +1 -1
  101. package/dist/cdn/login/snice-login.js +2 -2
  102. package/dist/cdn/login/snice-login.js.map +1 -1
  103. package/dist/cdn/login/snice-login.min.js +1 -1
  104. package/dist/cdn/login/snice-login.min.js.map +1 -1
  105. package/dist/cdn/map/snice-map.js +1 -1
  106. package/dist/cdn/markdown/snice-markdown.js +1 -1
  107. package/dist/cdn/masonry/snice-masonry.js +1 -1
  108. package/dist/cdn/menu/snice-menu.js +1 -1
  109. package/dist/cdn/message-strip/snice-message-strip.js +1 -1
  110. package/dist/cdn/modal/snice-modal.js +1 -1
  111. package/dist/cdn/music-player/snice-music-player.js +1 -1
  112. package/dist/cdn/nav/snice-nav.js +1 -1
  113. package/dist/cdn/network-graph/snice-network-graph.js +1 -1
  114. package/dist/cdn/notification-center/snice-notification-center.js +1 -1
  115. package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
  116. package/dist/cdn/org-chart/snice-org-chart.js +1 -1
  117. package/dist/cdn/pagination/snice-pagination.js +1 -1
  118. package/dist/cdn/paint/snice-paint.js +1 -1
  119. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
  120. package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
  121. package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
  122. package/dist/cdn/popover/snice-popover.js +1 -1
  123. package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
  124. package/dist/cdn/product-card/snice-product-card.js +1 -1
  125. package/dist/cdn/progress/snice-progress.js +1 -1
  126. package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
  127. package/dist/cdn/qr-code/snice-qr-code.js +1 -1
  128. package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
  129. package/dist/cdn/radio/snice-radio.js +1 -1
  130. package/dist/cdn/range-slider/snice-range-slider.js +1 -1
  131. package/dist/cdn/rating/snice-rating.js +1 -1
  132. package/dist/cdn/receipt/snice-receipt.js +1 -1
  133. package/dist/cdn/recipe/snice-recipe.js +1 -1
  134. package/dist/cdn/runtime/README.md +2 -2
  135. package/dist/cdn/runtime/snice-runtime.esm.js +706 -267
  136. package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
  137. package/dist/cdn/runtime/snice-runtime.esm.min.js +1 -1
  138. package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
  139. package/dist/cdn/runtime/snice-runtime.js +706 -267
  140. package/dist/cdn/runtime/snice-runtime.js.map +1 -1
  141. package/dist/cdn/runtime/snice-runtime.min.js +1 -1
  142. package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
  143. package/dist/cdn/sankey/snice-sankey.js +1 -1
  144. package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
  145. package/dist/cdn/select/snice-select.js +3 -1
  146. package/dist/cdn/select/snice-select.js.map +1 -1
  147. package/dist/cdn/select/snice-select.min.js +2 -2
  148. package/dist/cdn/select/snice-select.min.js.map +1 -1
  149. package/dist/cdn/skeleton/snice-skeleton.js +1 -1
  150. package/dist/cdn/slider/snice-slider.js +1 -1
  151. package/dist/cdn/sortable/snice-sortable.js +1 -1
  152. package/dist/cdn/sparkline/snice-sparkline.js +1 -1
  153. package/dist/cdn/spinner/snice-spinner.js +1 -1
  154. package/dist/cdn/split-button/snice-split-button.js +1 -1
  155. package/dist/cdn/split-pane/snice-split-pane.js +1 -1
  156. package/dist/cdn/spotlight/snice-spotlight.js +1 -1
  157. package/dist/cdn/stat-group/snice-stat-group.js +1 -1
  158. package/dist/cdn/step-input/snice-step-input.js +1 -1
  159. package/dist/cdn/stepper/snice-stepper.js +1 -1
  160. package/dist/cdn/switch/README.md +1 -1
  161. package/dist/cdn/switch/snice-switch.js +8 -4
  162. package/dist/cdn/switch/snice-switch.js.map +1 -1
  163. package/dist/cdn/switch/snice-switch.min.js +8 -4
  164. package/dist/cdn/switch/snice-switch.min.js.map +1 -1
  165. package/dist/cdn/table/README.md +2 -2
  166. package/dist/cdn/table/snice-table.esm.js +77 -5
  167. package/dist/cdn/table/snice-table.esm.js.map +1 -1
  168. package/dist/cdn/table/snice-table.esm.min.js +68 -47
  169. package/dist/cdn/table/snice-table.esm.min.js.map +1 -1
  170. package/dist/cdn/table/snice-table.js +76 -4
  171. package/dist/cdn/table/snice-table.js.map +1 -1
  172. package/dist/cdn/table/snice-table.min.js +53 -32
  173. package/dist/cdn/table/snice-table.min.js.map +1 -1
  174. package/dist/cdn/tabs/snice-tabs.js +1 -1
  175. package/dist/cdn/tag/snice-tag.js +1 -1
  176. package/dist/cdn/tag-input/snice-tag-input.js +1 -1
  177. package/dist/cdn/terminal/snice-terminal.js +1 -1
  178. package/dist/cdn/testimonial/snice-testimonial.js +1 -1
  179. package/dist/cdn/textarea/snice-textarea.js +1 -1
  180. package/dist/cdn/time-picker/snice-time-picker.js +1 -1
  181. package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
  182. package/dist/cdn/timeline/snice-timeline.js +1 -1
  183. package/dist/cdn/timer/snice-timer.js +1 -1
  184. package/dist/cdn/toast/snice-toast.js +1 -1
  185. package/dist/cdn/tooltip/snice-tooltip.js +1 -1
  186. package/dist/cdn/tree/snice-tree.js +1 -1
  187. package/dist/cdn/treemap/snice-treemap.js +1 -1
  188. package/dist/cdn/user-card/snice-user-card.js +1 -1
  189. package/dist/cdn/video-player/snice-video-player.js +1 -1
  190. package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
  191. package/dist/cdn/waterfall/snice-waterfall.js +1 -1
  192. package/dist/cdn/weather/snice-weather.js +1 -1
  193. package/dist/cdn/work-order/snice-work-order.js +1 -1
  194. package/dist/components/avatar/snice-avatar.d.ts +1 -0
  195. package/dist/components/avatar/snice-avatar.js +8 -2
  196. package/dist/components/avatar/snice-avatar.js.map +1 -1
  197. package/dist/components/avatar/snice-avatar.types.d.ts +2 -0
  198. package/dist/components/button/snice-button.js +1 -1
  199. package/dist/components/button/snice-button.js.map +1 -1
  200. package/dist/components/calendar/snice-calendar.d.ts +38 -1
  201. package/dist/components/calendar/snice-calendar.js +390 -40
  202. package/dist/components/calendar/snice-calendar.js.map +1 -1
  203. package/dist/components/calendar/snice-calendar.types.d.ts +63 -0
  204. package/dist/components/select/snice-select.js +2 -0
  205. package/dist/components/select/snice-select.js.map +1 -1
  206. package/dist/components/switch/snice-switch.js +7 -3
  207. package/dist/components/switch/snice-switch.js.map +1 -1
  208. package/dist/components/table/snice-table.d.ts +9 -0
  209. package/dist/components/table/snice-table.js +72 -2
  210. package/dist/components/table/snice-table.js.map +1 -1
  211. package/dist/components/table/table-keyboard.js +1 -1
  212. package/dist/components/table/table-keyboard.js.map +1 -1
  213. package/dist/index.cjs +703 -264
  214. package/dist/index.cjs.map +1 -1
  215. package/dist/index.d.ts +3 -1
  216. package/dist/index.esm.js +703 -264
  217. package/dist/index.esm.js.map +1 -1
  218. package/dist/index.iife.js +703 -264
  219. package/dist/index.iife.js.map +1 -1
  220. package/dist/parts.d.ts +14 -4
  221. package/dist/react/SniceProvider.js +1 -1
  222. package/dist/react/SniceRouter.js +1 -1
  223. package/dist/react/index.js +1 -1
  224. package/dist/react/matchRoute.js +68 -2
  225. package/dist/react/matchRoute.js.map +1 -1
  226. package/dist/react/route-match.d.ts +7 -0
  227. package/dist/react/useRequestHandler.js +1 -1
  228. package/dist/render-errors.d.ts +9 -0
  229. package/dist/route-match.d.ts +7 -0
  230. package/dist/symbols.cjs +1 -1
  231. package/dist/symbols.esm.js +1 -1
  232. package/dist/template-marker.d.ts +5 -0
  233. package/dist/testing-dom.cjs +1 -1
  234. package/dist/testing-dom.esm.js +1 -1
  235. package/dist/testing.d.ts +3 -0
  236. package/dist/transitions.cjs +1 -1
  237. package/dist/transitions.esm.js +1 -1
  238. package/dist/types/dispatch-options.d.ts +5 -4
  239. package/dist/types/event-timing.d.ts +7 -0
  240. package/dist/types/index.d.ts +1 -0
  241. package/dist/types/on-options.d.ts +21 -6
  242. package/dist/utils.d.ts +3 -0
  243. package/docs/ai/DEVELOPMENT.md +1 -1
  244. package/docs/ai/api.md +7 -2
  245. package/docs/ai/cli.md +14 -0
  246. package/docs/ai/components/avatar.md +1 -0
  247. package/docs/ai/components/calendar.md +24 -1
  248. package/docs/ai/components/switch.md +3 -0
  249. package/docs/ai/components/table.md +1 -1
  250. package/docs/ai/decorators.md +3 -2
  251. package/docs/ai/events.md +45 -8
  252. package/docs/ai/rendering.md +7 -0
  253. package/docs/ai/routing.md +6 -1
  254. package/docs/ai/testing.md +17 -0
  255. package/docs/cli.md +19 -0
  256. package/docs/components/avatar.md +1 -0
  257. package/docs/components/calendar.md +112 -2
  258. package/docs/components/switch.md +7 -1
  259. package/docs/components/table.md +2 -1
  260. package/docs/events.md +90 -10
  261. package/docs/rendering.md +10 -0
  262. package/docs/routing.md +22 -1
  263. package/docs/testing.md +19 -0
  264. package/package.json +2 -2
  265. package/vscode.html-custom-data.json +28 -0
@@ -1,7 +1,8 @@
1
1
  import { __runInitializers, __esDecorate } from 'tslib';
2
- import { element, property, dispatch, styles, ready, watch, css } from 'snice';
2
+ import { element, property, dispatch, styles, ready, request, dispose, watch, css } from 'snice';
3
+ import '../avatar/snice-avatar.js';
3
4
 
4
- var cssContent = ":host([hidden]){display:none}:host{display:block;font-family:var(--snice-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);contain:layout style}.calendar{width:100%;max-width:37.5rem}.calendar__header{font-family:var(--snice-font-family-display, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);display:flex;align-items:center;justify-content:space-between;padding:var(--snice-spacing-md,1rem);background:var(--snice-color-surface,rgb(255 255 255));border-bottom:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar__title{font-family:var(--snice-font-family-display, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);font-size:var(--snice-heading-md, 1.125rem);font-weight:var(--snice-font-weight-semibold,600);color:var(--snice-color-text,rgb(23 23 23))}.calendar__nav{display:flex;gap:var(--snice-spacing-xs,.5rem)}.calendar__nav-button{padding:var(--snice-spacing-xs,.5rem) var(--snice-spacing-sm,.75rem);border:1px solid var(--snice-color-border,rgb(226 226 226));background:var(--snice-color-surface,rgb(255 255 255));border-radius:var(--snice-border-radius-md,.25rem);cursor:pointer;transition:background-color var(--snice-transition-fast, 150ms) ease,border-color var(--snice-transition-fast, 150ms) ease;font-size:var(--snice-font-size-sm, .875rem);color:var(--snice-color-text,rgb(23 23 23));font-family:inherit}.calendar__nav-button:hover{background:var(--snice-color-surface-container-low,rgb(250 250 250));border-color:var(--snice-color-border-hover,rgb(204 204 204))}.calendar__nav-button:focus-visible{outline:0;box-shadow:0 0 0 var(--snice-focus-ring-width,2px) var(--snice-focus-ring-color,rgb(59 130 246 / .5))}.calendar__grid{display:grid;grid-template-columns:repeat(7,1fr);background:var(--snice-color-surface,rgb(255 255 255))}.calendar__weekday{padding:var(--snice-spacing-sm,.75rem);text-align:center;font-size:var(--snice-font-size-xs, .75rem);font-weight:var(--snice-font-weight-semibold,600);color:var(--snice-color-text-secondary,rgb(82 82 82));text-transform:uppercase;letter-spacing:var(--snice-tracking-widest, .1em);border-bottom:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar__day{aspect-ratio:1;min-height:3rem;padding:var(--snice-spacing-xs,.5rem);border:1px solid var(--snice-color-border,rgb(226 226 226));border-top:none;border-left:none;cursor:pointer;transition:background-color var(--snice-transition-fast, 150ms) ease;position:relative;background:var(--snice-color-surface,rgb(255 255 255));color:var(--snice-color-text,rgb(23 23 23));overflow:hidden}.calendar__day:hover{background:var(--snice-color-surface-container-low,rgb(250 250 250))}.calendar__day:focus-visible{outline:0;box-shadow:inset 0 0 0 2px var(--snice-focus-ring-color,rgb(59 130 246 / .5))}.calendar__day:nth-child(7n+1){border-left:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar__day--other-month{background:var(--snice-color-surface,rgb(255 255 255));color:var(--snice-color-text-tertiary,rgb(115 115 115));opacity:.5}.calendar__day--other-month:hover{opacity:.7}.calendar__day--today{background:var(--snice-color-primary-subtle,rgb(239 246 255))}.calendar__day--today:hover{background:var(--snice-color-primary-subtle-hover,rgb(219 234 254))}.calendar__day--selected{background:var(--snice-color-primary,rgb(37 99 235));color:var(--snice-color-text-inverse,rgb(250 250 250))}.calendar__day--selected:hover{background:var(--snice-color-primary-hover,rgb(29 78 216))}.calendar__day--disabled{background:var(--snice-color-surface-container,rgb(241 241 241));color:var(--snice-color-text-tertiary,rgb(115 115 115));opacity:.5;cursor:not-allowed}.calendar__day--disabled:hover{background:var(--snice-color-surface-container,rgb(241 241 241))}.calendar__day-number{font-size:var(--snice-font-size-sm, .875rem);font-weight:var(--snice-font-weight-medium,500);margin-bottom:var(--snice-spacing-2xs,.25rem)}.calendar__day--selected .calendar__day-number{color:var(--snice-color-text-inverse,rgb(250 250 250))}.calendar__events{display:flex;flex-direction:column;gap:var(--snice-spacing-3xs,.125rem);margin-top:var(--snice-spacing-2xs,.25rem)}.calendar__event{font-size:var(--snice-font-size-2xs, .625rem);padding:var(--snice-spacing-3xs,.125rem) var(--snice-spacing-2xs,.25rem);border-radius:var(--snice-border-radius-sm,.125rem);background:var(--snice-color-primary,rgb(37 99 235));color:var(--snice-color-text-inverse,rgb(250 250 250));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:opacity var(--snice-transition-fast, 150ms) ease}.calendar__event:hover{opacity:.8}.calendar__week-number{padding:var(--snice-spacing-sm,.75rem) var(--snice-spacing-xs,.5rem);text-align:center;font-size:var(--snice-font-size-xs, .75rem);color:var(--snice-color-text-tertiary,rgb(115 115 115));background:var(--snice-color-surface-container-low,rgb(250 250 250));border-right:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar--week .calendar__grid{grid-template-columns:repeat(7,1fr)}.calendar--week .calendar__day{min-height:7.5rem}.calendar--day .calendar__grid{grid-template-columns:1fr}.calendar--day .calendar__day{min-height:25rem}@media (prefers-reduced-motion:reduce){*{transition-duration:0s!important;animation-duration:0s!important}}";
5
+ var cssContent = ":host([hidden]){display:none}:host{display:block;font-family:var(--snice-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);contain:layout style}.calendar{width:100%;max-width:37.5rem}.calendar__header{font-family:var(--snice-font-family-display, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);display:flex;align-items:center;justify-content:space-between;padding:var(--snice-spacing-md,1rem);background:var(--snice-color-surface,rgb(255 255 255));border-bottom:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar__title{font-family:var(--snice-font-family-display, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif);font-size:var(--snice-heading-md, 1.125rem);font-weight:var(--snice-font-weight-semibold,600);color:var(--snice-color-text,rgb(23 23 23))}.calendar__nav{display:flex;gap:var(--snice-spacing-xs,.5rem)}.calendar__nav-button{padding:var(--snice-spacing-xs,.5rem) var(--snice-spacing-sm,.75rem);border:1px solid var(--snice-color-border,rgb(226 226 226));background:var(--snice-color-surface,rgb(255 255 255));border-radius:var(--snice-border-radius-md,.25rem);cursor:pointer;transition:background-color var(--snice-transition-fast, 150ms) ease,border-color var(--snice-transition-fast, 150ms) ease;font-size:var(--snice-font-size-sm, .875rem);color:var(--snice-color-text,rgb(23 23 23));font-family:inherit}.calendar__nav-button:hover{background:var(--snice-color-surface-container-low,rgb(250 250 250));border-color:var(--snice-color-border-hover,rgb(204 204 204))}.calendar__nav-button:focus-visible{outline:0;box-shadow:0 0 0 var(--snice-focus-ring-width,2px) var(--snice-focus-ring-color,rgb(59 130 246 / .5))}.calendar__grid{display:grid;grid-template-columns:repeat(7,1fr);background:var(--snice-color-surface,rgb(255 255 255));container-type:inline-size}.calendar__weekday{padding:var(--snice-spacing-sm,.75rem);text-align:center;font-size:var(--snice-font-size-xs, .75rem);font-weight:var(--snice-font-weight-semibold,600);color:var(--snice-color-text-secondary,rgb(82 82 82));text-transform:uppercase;letter-spacing:var(--snice-tracking-widest, .1em);border-bottom:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar__day{box-sizing:border-box;min-width:0;min-height:max(calc(100cqw / 7),3rem,calc(2.125rem + var(--calendar-week-lanes,0) * 1.375rem + var(--calendar-week-more,0rem)));padding:var(--snice-spacing-xs,.5rem);border:1px solid var(--snice-color-border,rgb(226 226 226));border-top:none;border-left:none;cursor:pointer;transition:background-color var(--snice-transition-fast, 150ms) ease;position:relative;background:var(--snice-color-surface,rgb(255 255 255));color:var(--snice-color-text,rgb(23 23 23));overflow:hidden}.calendar__day:hover{background:var(--snice-color-surface-container-low,rgb(250 250 250))}.calendar__day:focus-visible{outline:0;box-shadow:inset 0 0 0 2px var(--snice-focus-ring-color,rgb(59 130 246 / .5))}.calendar__day:nth-child(7n+1){border-left:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar__day--stretch{min-height:max(3rem,calc(2.125rem + var(--calendar-week-lanes,0) * 1.375rem + var(--calendar-week-more,0rem)))}.calendar__day--static{cursor:default}.calendar__day--static:hover{background:var(--snice-color-surface,rgb(255 255 255))}.calendar__day--static.calendar__day--today:hover{background:var(--snice-color-primary-subtle,rgb(239 246 255))}.calendar__day--other-month{background:var(--snice-color-surface,rgb(255 255 255));color:var(--snice-color-text-tertiary,rgb(115 115 115));opacity:.5}.calendar__day--other-month:hover{opacity:.7}.calendar__day--today{background:var(--snice-color-primary-subtle,rgb(239 246 255))}.calendar__day--today:hover{background:var(--snice-color-primary-subtle-hover,rgb(219 234 254))}.calendar__day--selected{background:var(--snice-color-primary,rgb(37 99 235));color:var(--snice-color-text-inverse,rgb(250 250 250))}.calendar__day--selected:hover{background:var(--snice-color-primary-hover,rgb(29 78 216))}.calendar__day--disabled{background:var(--snice-color-surface-container,rgb(241 241 241));color:var(--snice-color-text-tertiary,rgb(115 115 115));opacity:.5;cursor:not-allowed}.calendar__day--disabled:hover{background:var(--snice-color-surface-container,rgb(241 241 241))}.calendar__day-number{font-size:var(--snice-font-size-sm, .875rem);font-weight:var(--snice-font-weight-medium,500);margin-bottom:var(--snice-spacing-2xs,.25rem)}.calendar__day--selected .calendar__day-number{color:var(--snice-color-text-inverse,rgb(250 250 250))}.calendar__event-bar{display:flex;align-items:center;gap:var(--snice-spacing-3xs,.125rem);align-self:start;margin-top:calc(1.875rem + var(--calendar-event-lane,0) * 1.375rem);margin-inline:var(--snice-spacing-3xs,0.125rem);height:1.125rem;line-height:1.125rem;font-size:var(--snice-font-size-2xs, .625rem);padding:0 var(--snice-spacing-2xs,.25rem);border-radius:var(--snice-border-radius-sm,.125rem);background:var(--snice-color-primary,rgb(37 99 235));color:var(--snice-color-text-inverse,rgb(250 250 250));white-space:nowrap;overflow:hidden;cursor:pointer;z-index:1;transition:opacity var(--snice-transition-fast, 150ms) ease}.calendar__event-title{overflow:hidden;text-overflow:ellipsis;min-width:0}.calendar__event-avatar{flex:none;--avatar-size:0.875rem;font-size:.375rem;border-radius:50%;overflow:hidden}.calendar__popover{position:fixed;z-index:var(--snice-z-floating,1000);min-width:14rem;max-width:22rem;padding:var(--snice-spacing-sm,.75rem);border:1px solid var(--snice-color-border,rgb(226 226 226));border-radius:var(--snice-border-radius-md,.25rem);background:var(--snice-color-surface,rgb(255 255 255));color:var(--snice-color-text,rgb(23 23 23));font-size:var(--snice-font-size-sm, .875rem);line-height:1.5;box-shadow:var(--snice-shadow-lg,0 10px 15px -3px rgb(0 0 0 / .1))}.calendar__popover:focus-visible{outline:0;box-shadow:var(--snice-shadow-lg,0 10px 15px -3px rgb(0 0 0 / .1)),0 0 0 var(--snice-focus-ring-width,2px) var(--snice-focus-ring-color,rgb(59 130 246 / .5))}.calendar__popover-loading{color:var(--snice-color-text-secondary,rgb(82 82 82));font-size:var(--snice-font-size-xs, .75rem)}.calendar__tooltip{position:fixed;z-index:var(--snice-z-floating,1000);max-width:18rem;padding:var(--snice-spacing-2xs,.25rem) var(--snice-spacing-xs,.5rem);border-radius:var(--snice-border-radius-md,.25rem);background:var(--snice-tooltip-bg,rgb(51 51 51));color:var(--snice-color-text-inverse,rgb(250 250 250));font-size:var(--snice-font-size-xs, .75rem);line-height:1.4;box-shadow:var(--snice-shadow-md,0 4px 6px -1px rgb(0 0 0 / .1));pointer-events:none}.calendar__event-bar:hover{opacity:.8}.calendar__event-bar--continues-left{border-top-left-radius:0;border-bottom-left-radius:0;margin-inline-start:0}.calendar__event-bar--continues-right{border-top-right-radius:0;border-bottom-right-radius:0;margin-inline-end:0}.calendar__more{position:absolute;bottom:var(--snice-spacing-3xs,.125rem);left:var(--snice-spacing-2xs,.25rem);font-size:var(--snice-font-size-2xs, .625rem);color:var(--snice-color-text-secondary,rgb(82 82 82))}.calendar__week-number{padding:var(--snice-spacing-sm,.75rem) var(--snice-spacing-xs,.5rem);text-align:center;font-size:var(--snice-font-size-xs, .75rem);color:var(--snice-color-text-tertiary,rgb(115 115 115));background:var(--snice-color-surface-container-low,rgb(250 250 250));border-right:1px solid var(--snice-color-border,rgb(226 226 226))}.calendar--week .calendar__grid{grid-template-columns:repeat(7,1fr)}.calendar--week .calendar__day{min-height:7.5rem}.calendar--day .calendar__grid{grid-template-columns:1fr}.calendar--day .calendar__day{min-height:25rem}@media (prefers-reduced-motion:reduce){*{transition-duration:0s!important;animation-duration:0s!important}}";
5
6
 
6
7
  let SniceCalendar = (() => {
7
8
  let _classDecorators = [element('snice-calendar')];
@@ -40,13 +41,27 @@ let SniceCalendar = (() => {
40
41
  let _locale_decorators;
41
42
  let _locale_initializers = [];
42
43
  let _locale_extraInitializers = [];
44
+ let _noDaySelect_decorators;
45
+ let _noDaySelect_initializers = [];
46
+ let _noDaySelect_extraInitializers = [];
47
+ let _cellSizing_decorators;
48
+ let _cellSizing_initializers = [];
49
+ let _cellSizing_extraInitializers = [];
50
+ let _eventTooltip_decorators;
51
+ let _eventTooltip_initializers = [];
52
+ let _eventTooltip_extraInitializers = [];
53
+ let _eventPopover_decorators;
54
+ let _eventPopover_initializers = [];
55
+ let _eventPopover_extraInitializers = [];
43
56
  let _dispatchChange_decorators;
44
57
  let _dispatchEventClick_decorators;
45
58
  let _styles_decorators;
46
59
  let _initialize_decorators;
60
+ let _requestEventPopoverContent_decorators;
61
+ let _cleanupPopover_decorators;
47
62
  let _handlePropertyChange_decorators;
48
63
  let _handleWeekdayInputsChange_decorators;
49
- (class extends _classSuper {
64
+ var SniceCalendar = class extends _classSuper {
50
65
  static { _classThis = this; }
51
66
  constructor() {
52
67
  super(...arguments);
@@ -60,7 +75,26 @@ let SniceCalendar = (() => {
60
75
  this.showWeekNumbers = (__runInitializers(this, _highlightToday_extraInitializers), __runInitializers(this, _showWeekNumbers_initializers, false));
61
76
  this.firstDayOfWeek = (__runInitializers(this, _showWeekNumbers_extraInitializers), __runInitializers(this, _firstDayOfWeek_initializers, 0)); // 0 = Sunday, 1 = Monday
62
77
  this.locale = (__runInitializers(this, _firstDayOfWeek_extraInitializers), __runInitializers(this, _locale_initializers, 'en-US'));
63
- this.displayDate = (__runInitializers(this, _locale_extraInitializers), new Date());
78
+ this.noDaySelect = (__runInitializers(this, _locale_extraInitializers), __runInitializers(this, _noDaySelect_initializers, false));
79
+ this.cellSizing = (__runInitializers(this, _noDaySelect_extraInitializers), __runInitializers(this, _cellSizing_initializers, 'square'));
80
+ this.eventTooltip = (__runInitializers(this, _cellSizing_extraInitializers), __runInitializers(this, _eventTooltip_initializers, null));
81
+ this.eventPopover = (__runInitializers(this, _eventTooltip_extraInitializers), __runInitializers(this, _eventPopover_initializers, null));
82
+ this.displayDate = (__runInitializers(this, _eventPopover_extraInitializers), new Date());
83
+ this.tooltipToken = 0;
84
+ this.tooltipBar = null;
85
+ this.popoverToken = 0;
86
+ this.popoverBar = null;
87
+ this.boundPopoverEscape = (e) => {
88
+ if (e.key === 'Escape' && this.popoverBar)
89
+ this.closeEventPopover();
90
+ };
91
+ this.boundPopoverOutside = (e) => {
92
+ if (!this.popoverBar)
93
+ return;
94
+ if (e.composedPath().includes(this.popoverEl))
95
+ return;
96
+ this.closeEventPopover({ returnFocus: false });
97
+ };
64
98
  this.dayCells = [];
65
99
  this.focusedDate = null;
66
100
  this.handleGridKeydown = (e) => {
@@ -137,16 +171,24 @@ let SniceCalendar = (() => {
137
171
  _showWeekNumbers_decorators = [property({ type: Boolean, attribute: 'show-week-numbers' })];
138
172
  _firstDayOfWeek_decorators = [property({ type: Number, attribute: 'first-day-of-week' })];
139
173
  _locale_decorators = [property({ attribute: 'locale' })];
174
+ _noDaySelect_decorators = [property({ type: Boolean, attribute: 'no-day-select' })];
175
+ _cellSizing_decorators = [property({ attribute: 'cell-sizing' })];
176
+ _eventTooltip_decorators = [property({ attribute: false })];
177
+ _eventPopover_decorators = [property({ attribute: false })];
140
178
  _dispatchChange_decorators = [dispatch('calendar-change', { bubbles: true, composed: true })];
141
179
  _dispatchEventClick_decorators = [dispatch('calendar-event-click', { bubbles: true, composed: true })];
142
180
  _styles_decorators = [styles()];
143
181
  _initialize_decorators = [ready()];
144
- _handlePropertyChange_decorators = [watch('value'), watch('events')];
182
+ _requestEventPopoverContent_decorators = [request('calendar/event-popover')];
183
+ _cleanupPopover_decorators = [dispose()];
184
+ _handlePropertyChange_decorators = [watch('value'), watch('events'), watch('eventTooltip'), watch('noDaySelect'), watch('cellSizing')];
145
185
  _handleWeekdayInputsChange_decorators = [watch('locale'), watch('firstDayOfWeek')];
146
186
  __esDecorate(this, null, _dispatchChange_decorators, { kind: "method", name: "dispatchChange", static: false, private: false, access: { has: obj => "dispatchChange" in obj, get: obj => obj.dispatchChange }, metadata: _metadata }, null, _instanceExtraInitializers);
147
187
  __esDecorate(this, null, _dispatchEventClick_decorators, { kind: "method", name: "dispatchEventClick", static: false, private: false, access: { has: obj => "dispatchEventClick" in obj, get: obj => obj.dispatchEventClick }, metadata: _metadata }, null, _instanceExtraInitializers);
148
188
  __esDecorate(this, null, _styles_decorators, { kind: "method", name: "styles", static: false, private: false, access: { has: obj => "styles" in obj, get: obj => obj.styles }, metadata: _metadata }, null, _instanceExtraInitializers);
149
189
  __esDecorate(this, null, _initialize_decorators, { kind: "method", name: "initialize", static: false, private: false, access: { has: obj => "initialize" in obj, get: obj => obj.initialize }, metadata: _metadata }, null, _instanceExtraInitializers);
190
+ __esDecorate(this, null, _requestEventPopoverContent_decorators, { kind: "method", name: "requestEventPopoverContent", static: false, private: false, access: { has: obj => "requestEventPopoverContent" in obj, get: obj => obj.requestEventPopoverContent }, metadata: _metadata }, null, _instanceExtraInitializers);
191
+ __esDecorate(this, null, _cleanupPopover_decorators, { kind: "method", name: "cleanupPopover", static: false, private: false, access: { has: obj => "cleanupPopover" in obj, get: obj => obj.cleanupPopover }, metadata: _metadata }, null, _instanceExtraInitializers);
150
192
  __esDecorate(this, null, _handlePropertyChange_decorators, { kind: "method", name: "handlePropertyChange", static: false, private: false, access: { has: obj => "handlePropertyChange" in obj, get: obj => obj.handlePropertyChange }, metadata: _metadata }, null, _instanceExtraInitializers);
151
193
  __esDecorate(this, null, _handleWeekdayInputsChange_decorators, { kind: "method", name: "handleWeekdayInputsChange", static: false, private: false, access: { has: obj => "handleWeekdayInputsChange" in obj, get: obj => obj.handleWeekdayInputsChange }, metadata: _metadata }, null, _instanceExtraInitializers);
152
194
  __esDecorate(null, null, _value_decorators, { kind: "field", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
@@ -159,10 +201,13 @@ let SniceCalendar = (() => {
159
201
  __esDecorate(null, null, _showWeekNumbers_decorators, { kind: "field", name: "showWeekNumbers", static: false, private: false, access: { has: obj => "showWeekNumbers" in obj, get: obj => obj.showWeekNumbers, set: (obj, value) => { obj.showWeekNumbers = value; } }, metadata: _metadata }, _showWeekNumbers_initializers, _showWeekNumbers_extraInitializers);
160
202
  __esDecorate(null, null, _firstDayOfWeek_decorators, { kind: "field", name: "firstDayOfWeek", static: false, private: false, access: { has: obj => "firstDayOfWeek" in obj, get: obj => obj.firstDayOfWeek, set: (obj, value) => { obj.firstDayOfWeek = value; } }, metadata: _metadata }, _firstDayOfWeek_initializers, _firstDayOfWeek_extraInitializers);
161
203
  __esDecorate(null, null, _locale_decorators, { kind: "field", name: "locale", static: false, private: false, access: { has: obj => "locale" in obj, get: obj => obj.locale, set: (obj, value) => { obj.locale = value; } }, metadata: _metadata }, _locale_initializers, _locale_extraInitializers);
204
+ __esDecorate(null, null, _noDaySelect_decorators, { kind: "field", name: "noDaySelect", static: false, private: false, access: { has: obj => "noDaySelect" in obj, get: obj => obj.noDaySelect, set: (obj, value) => { obj.noDaySelect = value; } }, metadata: _metadata }, _noDaySelect_initializers, _noDaySelect_extraInitializers);
205
+ __esDecorate(null, null, _cellSizing_decorators, { kind: "field", name: "cellSizing", static: false, private: false, access: { has: obj => "cellSizing" in obj, get: obj => obj.cellSizing, set: (obj, value) => { obj.cellSizing = value; } }, metadata: _metadata }, _cellSizing_initializers, _cellSizing_extraInitializers);
206
+ __esDecorate(null, null, _eventTooltip_decorators, { kind: "field", name: "eventTooltip", static: false, private: false, access: { has: obj => "eventTooltip" in obj, get: obj => obj.eventTooltip, set: (obj, value) => { obj.eventTooltip = value; } }, metadata: _metadata }, _eventTooltip_initializers, _eventTooltip_extraInitializers);
207
+ __esDecorate(null, null, _eventPopover_decorators, { kind: "field", name: "eventPopover", static: false, private: false, access: { has: obj => "eventPopover" in obj, get: obj => obj.eventPopover, set: (obj, value) => { obj.eventPopover = value; } }, metadata: _metadata }, _eventPopover_initializers, _eventPopover_extraInitializers);
162
208
  __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
163
- _classThis = _classDescriptor.value;
209
+ SniceCalendar = _classThis = _classDescriptor.value;
164
210
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
165
- __runInitializers(_classThis, _classExtraInitializers);
166
211
  }
167
212
  computeRovingIndex(days) {
168
213
  // Prefer: focused → selected → today → first in-month day
@@ -236,12 +281,16 @@ let SniceCalendar = (() => {
236
281
  this.grid = document.createElement('div');
237
282
  this.grid.className = 'calendar__grid';
238
283
  this.grid.setAttribute('part', 'grid');
239
- // Add weekday headers
284
+ // Add weekday headers. Every grid child gets an explicit position —
285
+ // event stripe bars are placed explicitly, and mixing explicit items
286
+ // with auto-flow would push auto-placed cells out of their slots.
240
287
  const weekdays = this.getWeekdays();
241
- weekdays.forEach(day => {
288
+ weekdays.forEach((day, i) => {
242
289
  const weekdayEl = document.createElement('div');
243
290
  weekdayEl.className = 'calendar__weekday';
244
291
  weekdayEl.textContent = day;
292
+ weekdayEl.style.gridRow = '1';
293
+ weekdayEl.style.gridColumn = String(i + 1);
245
294
  this.grid.appendChild(weekdayEl);
246
295
  });
247
296
  // Mark grid for a11y
@@ -257,20 +306,147 @@ let SniceCalendar = (() => {
257
306
  // making the first cell tabbable; updateView re-targets the focused
258
307
  // date so today/selected gets the 0.
259
308
  dayCell.setAttribute('tabindex', i === 0 ? '0' : '-1');
309
+ dayCell.style.gridRow = String(Math.floor(i / 7) + 2);
310
+ dayCell.style.gridColumn = String((i % 7) + 1);
260
311
  const dayNumber = document.createElement('div');
261
312
  dayNumber.className = 'calendar__day-number';
262
313
  dayCell.appendChild(dayNumber);
263
- const eventsContainer = document.createElement('div');
264
- eventsContainer.className = 'calendar__events';
265
- eventsContainer.style.display = 'none';
266
- dayCell.appendChild(eventsContainer);
267
314
  this.grid.appendChild(dayCell);
268
315
  this.dayCells.push(dayCell);
269
316
  }
317
+ // Shared tooltip overlay for event bars — one element, repositioned per
318
+ // bar, so rich content can load lazily without a tooltip instance per bar.
319
+ this.tooltipEl = document.createElement('div');
320
+ this.tooltipEl.className = 'calendar__tooltip';
321
+ this.tooltipEl.setAttribute('part', 'event-tooltip');
322
+ this.tooltipEl.setAttribute('role', 'tooltip');
323
+ this.tooltipEl.id = 'calendar-event-tooltip';
324
+ this.tooltipEl.hidden = true;
325
+ // Interactive click-to-open popover for event details. One shared panel,
326
+ // anchored per bar; content may load lazily (provider or the
327
+ // calendar/event-popover request channel).
328
+ this.popoverEl = document.createElement('div');
329
+ this.popoverEl.className = 'calendar__popover';
330
+ this.popoverEl.setAttribute('part', 'event-popover');
331
+ this.popoverEl.setAttribute('role', 'dialog');
332
+ this.popoverEl.setAttribute('aria-label', 'Event details');
333
+ this.popoverEl.tabIndex = -1;
334
+ this.popoverEl.hidden = true;
270
335
  this.container.appendChild(this.header);
271
336
  this.container.appendChild(this.grid);
337
+ this.container.appendChild(this.tooltipEl);
338
+ this.container.appendChild(this.popoverEl);
272
339
  shadow.appendChild(this.container);
273
340
  }
341
+ /**
342
+ * Dynamic popover channel: yields `{ event }` so any
343
+ * `@respond('calendar/event-popover')` controller can return the content.
344
+ */
345
+ async *requestEventPopoverContent(event) {
346
+ return await (yield { event });
347
+ }
348
+ async openEventPopover(bar, event) {
349
+ const token = ++this.popoverToken;
350
+ this.hideEventTooltip();
351
+ // Anchor + loading shell first, so slow content still feels responsive.
352
+ this.popoverBar = bar;
353
+ this.popoverEl.replaceChildren();
354
+ const loading = document.createElement('div');
355
+ loading.className = 'calendar__popover-loading';
356
+ loading.textContent = 'Loading…';
357
+ this.popoverEl.appendChild(loading);
358
+ this.popoverEl.hidden = false;
359
+ this.positionPopover(bar);
360
+ document.addEventListener('keydown', this.boundPopoverEscape, true);
361
+ document.addEventListener('mousedown', this.boundPopoverOutside, true);
362
+ let content;
363
+ try {
364
+ if (event.popover !== true && event.popover) {
365
+ content = typeof event.popover === 'function' ? event.popover() : event.popover;
366
+ }
367
+ else if (this.eventPopover) {
368
+ content = await this.eventPopover(event);
369
+ }
370
+ else {
371
+ content = await this.requestEventPopoverContent(event);
372
+ }
373
+ }
374
+ catch {
375
+ // No responder discovered (or the provider failed) — close quietly.
376
+ content = undefined;
377
+ }
378
+ if (token !== this.popoverToken)
379
+ return; // closed (or replaced) meanwhile
380
+ if (content == null) {
381
+ console.warn(`[snice-calendar] event "${String(event.id)}" enables a popover but no content was provided — set eventPopover, event.popover content, or a @respond('calendar/event-popover') handler.`);
382
+ this.closeEventPopover({ returnFocus: false });
383
+ return;
384
+ }
385
+ if (typeof content === 'string')
386
+ this.popoverEl.textContent = content;
387
+ else
388
+ this.popoverEl.replaceChildren(content);
389
+ this.positionPopover(bar);
390
+ this.popoverEl.focus();
391
+ }
392
+ positionPopover(bar) {
393
+ const rect = bar.getBoundingClientRect();
394
+ this.popoverEl.style.left = `${Math.max(4, rect.left)}px`;
395
+ this.popoverEl.style.top = `${rect.bottom + 6}px`;
396
+ }
397
+ closeEventPopover(options = {}) {
398
+ if (!this.popoverBar)
399
+ return;
400
+ this.popoverToken++;
401
+ const bar = this.popoverBar;
402
+ this.popoverBar = null;
403
+ this.popoverEl.hidden = true;
404
+ this.popoverEl.replaceChildren();
405
+ document.removeEventListener('keydown', this.boundPopoverEscape, true);
406
+ document.removeEventListener('mousedown', this.boundPopoverOutside, true);
407
+ if (options.returnFocus !== false && bar.isConnected)
408
+ bar.focus();
409
+ }
410
+ cleanupPopover() {
411
+ document.removeEventListener('keydown', this.boundPopoverEscape, true);
412
+ document.removeEventListener('mousedown', this.boundPopoverOutside, true);
413
+ }
414
+ async showEventTooltip(bar, event) {
415
+ const token = ++this.tooltipToken;
416
+ const provider = this.eventTooltip;
417
+ let content;
418
+ if (provider) {
419
+ try {
420
+ content = await provider(event);
421
+ }
422
+ catch {
423
+ content = event.tooltip;
424
+ }
425
+ }
426
+ else {
427
+ content = event.tooltip;
428
+ }
429
+ // Pointer already left (or moved to another bar) while loading.
430
+ if (token !== this.tooltipToken || content == null)
431
+ return;
432
+ if (typeof content === 'string')
433
+ this.tooltipEl.textContent = content;
434
+ else
435
+ this.tooltipEl.replaceChildren(content);
436
+ this.tooltipEl.hidden = false;
437
+ this.tooltipBar = bar;
438
+ bar.setAttribute('aria-describedby', this.tooltipEl.id);
439
+ // Fixed positioning above the bar, clamped to the viewport.
440
+ const rect = bar.getBoundingClientRect();
441
+ this.tooltipEl.style.left = `${Math.max(4, rect.left)}px`;
442
+ this.tooltipEl.style.top = `${Math.max(4, rect.top - this.tooltipEl.offsetHeight - 6)}px`;
443
+ }
444
+ hideEventTooltip() {
445
+ this.tooltipToken++;
446
+ this.tooltipEl.hidden = true;
447
+ this.tooltipBar?.removeAttribute('aria-describedby');
448
+ this.tooltipBar = null;
449
+ }
274
450
  updateView() {
275
451
  // Update header title
276
452
  const monthName = this.displayDate.toLocaleDateString(this.locale, { month: 'long', year: 'numeric' });
@@ -288,9 +464,9 @@ let SniceCalendar = (() => {
288
464
  return;
289
465
  const isOtherMonth = date.getMonth() !== currentMonth;
290
466
  const isToday = this.highlightToday && this.isToday(date);
291
- const isSelected = this.isSelected(date);
467
+ // Display-only mode never shows a selection highlight.
468
+ const isSelected = !this.noDaySelect && this.isSelected(date);
292
469
  const isDisabled = this.isDisabled(date);
293
- const dayEvents = this.getEventsForDate(date);
294
470
  // Update classes (preserving role)
295
471
  cell.className = 'calendar__day';
296
472
  if (isOtherMonth)
@@ -301,6 +477,10 @@ let SniceCalendar = (() => {
301
477
  cell.classList.add('calendar__day--selected');
302
478
  if (isDisabled)
303
479
  cell.classList.add('calendar__day--disabled');
480
+ if (this.noDaySelect)
481
+ cell.classList.add('calendar__day--static');
482
+ if (this.cellSizing === 'stretch')
483
+ cell.classList.add('calendar__day--stretch');
304
484
  cell.setAttribute('role', 'gridcell');
305
485
  cell.setAttribute('aria-selected', isSelected ? 'true' : 'false');
306
486
  cell.setAttribute('aria-disabled', isDisabled ? 'true' : 'false');
@@ -314,34 +494,196 @@ let SniceCalendar = (() => {
314
494
  dayNumber.textContent = String(date.getDate());
315
495
  // Update click handler
316
496
  cell.onclick = () => this.handleDayClick(date);
317
- // Update events
318
- const eventsContainer = cell.querySelector('.calendar__events');
319
- if (eventsContainer) {
320
- if (dayEvents.length > 0) {
321
- eventsContainer.style.display = '';
322
- eventsContainer.innerHTML = '';
323
- dayEvents.slice(0, 3).forEach(event => {
324
- const eventEl = document.createElement('div');
325
- eventEl.className = 'calendar__event';
326
- if (event.color)
327
- eventEl.style.background = event.color;
328
- eventEl.textContent = event.title;
329
- eventEl.onclick = (e) => this.handleEventClick(event, e);
330
- eventsContainer.appendChild(eventEl);
331
- });
332
- if (dayEvents.length > 3) {
333
- const moreEl = document.createElement('div');
334
- moreEl.className = 'calendar__event';
335
- moreEl.style.background = '#999';
336
- moreEl.textContent = `+${dayEvents.length - 3} more`;
337
- eventsContainer.appendChild(moreEl);
338
- }
497
+ });
498
+ this.renderEventStripes(days);
499
+ }
500
+ /** Visible stacking depth for event stripes; deeper lanes collapse into a
501
+ * per-day "+N more" chip. */
502
+ static { this.MAX_EVENT_LANES = 3; }
503
+ /**
504
+ * Render events as continuous stripes: one bar per (event × week row),
505
+ * spanning the event's days in that week and chopped at week boundaries
506
+ * with continues-left/right styling. Overlapping events stack into lanes
507
+ * per week — earlier start first, longer event first on ties — like
508
+ * professional calendars.
509
+ */
510
+ renderEventStripes(days) {
511
+ this.closeEventPopover({ returnFocus: false }); // anchors are re-created
512
+ this.grid.querySelectorAll('.calendar__event-bar').forEach(el => el.remove());
513
+ this.dayCells.forEach(cell => {
514
+ cell.querySelector('.calendar__more')?.remove();
515
+ cell.style.removeProperty('--calendar-week-lanes');
516
+ cell.style.removeProperty('--calendar-week-more');
517
+ });
518
+ if (!this.events || this.events.length === 0)
519
+ return;
520
+ // Local-midnight timestamps for the visible grid; events normalize to the
521
+ // same construction so lookups are exact (and DST-safe).
522
+ const dayTimes = days.map(d => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime());
523
+ const dayIndex = new Map(dayTimes.map((t, i) => [t, i]));
524
+ const gridStart = dayTimes[0];
525
+ const gridEnd = dayTimes[dayTimes.length - 1];
526
+ const normalize = (d) => {
527
+ const date = typeof d === 'string' ? new Date(d) : d;
528
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
529
+ };
530
+ const resolved = [];
531
+ this.events.forEach((event, order) => {
532
+ if (!event.start)
533
+ return;
534
+ const startTime = normalize(event.start);
535
+ if (isNaN(startTime))
536
+ return;
537
+ const endTime = event.end ? Math.max(normalize(event.end), startTime) : startTime;
538
+ if (isNaN(endTime) || endTime < gridStart || startTime > gridEnd)
539
+ return;
540
+ const startsBeforeGrid = startTime < gridStart;
541
+ const endsAfterGrid = endTime > gridEnd;
542
+ const startIdx = startsBeforeGrid ? 0 : dayIndex.get(startTime);
543
+ const endIdx = endsAfterGrid ? dayTimes.length - 1 : dayIndex.get(endTime);
544
+ resolved.push({
545
+ event, startIdx, endIdx, startsBeforeGrid, endsAfterGrid,
546
+ startTime, duration: endTime - startTime, order,
547
+ });
548
+ });
549
+ resolved.sort((a, b) => a.startTime - b.startTime || b.duration - a.duration || a.order - b.order);
550
+ const hiddenPerDay = new Array(dayTimes.length).fill(0);
551
+ const weekCount = Math.floor(dayTimes.length / 7);
552
+ const weekLaneCounts = new Array(weekCount).fill(0);
553
+ for (let week = 0; week < weekCount; week++) {
554
+ const weekStart = week * 7;
555
+ const weekEnd = weekStart + 6;
556
+ // lanes[lane] holds the occupied [startCol, endCol] ranges in this week.
557
+ const lanes = [];
558
+ for (const item of resolved) {
559
+ if (item.endIdx < weekStart || item.startIdx > weekEnd)
560
+ continue;
561
+ const segStart = Math.max(item.startIdx, weekStart);
562
+ const segEnd = Math.min(item.endIdx, weekEnd);
563
+ const startCol = segStart - weekStart;
564
+ const endCol = segEnd - weekStart;
565
+ let lane = 0;
566
+ while (lanes[lane]?.some(([s, e]) => startCol <= e && endCol >= s))
567
+ lane++;
568
+ (lanes[lane] ??= []).push([startCol, endCol]);
569
+ weekLaneCounts[week] = Math.min(Math.max(weekLaneCounts[week], lane + 1), SniceCalendar.MAX_EVENT_LANES);
570
+ if (lane >= SniceCalendar.MAX_EVENT_LANES) {
571
+ for (let i = segStart; i <= segEnd; i++)
572
+ hiddenPerDay[i]++;
573
+ continue;
574
+ }
575
+ const continuesLeft = segStart > item.startIdx
576
+ || (segStart === item.startIdx && item.startsBeforeGrid);
577
+ const continuesRight = segEnd < item.endIdx
578
+ || (segEnd === item.endIdx && item.endsAfterGrid);
579
+ const bar = document.createElement('div');
580
+ bar.className = 'calendar__event-bar';
581
+ if (continuesLeft)
582
+ bar.classList.add('calendar__event-bar--continues-left');
583
+ if (continuesRight)
584
+ bar.classList.add('calendar__event-bar--continues-right');
585
+ // A custom className rides along on both the class list and the part
586
+ // attribute, so events are styleable from outside via
587
+ // ::part(<className>).
588
+ const customClasses = item.event.className
589
+ ? item.event.className.split(/\s+/).filter(Boolean)
590
+ : [];
591
+ bar.classList.add(...customClasses);
592
+ bar.setAttribute('part', ['event-bar', ...customClasses].join(' '));
593
+ bar.setAttribute('data-event-id', String(item.event.id));
594
+ bar.setAttribute('data-lane', String(lane));
595
+ bar.style.gridRow = String(week + 2); // row 1 is the weekday header
596
+ bar.style.gridColumn = `${startCol + 1} / ${endCol + 2}`;
597
+ bar.style.setProperty('--calendar-event-lane', String(lane));
598
+ if (item.event.color)
599
+ bar.style.background = item.event.color;
600
+ if (item.event.avatar) {
601
+ const spec = typeof item.event.avatar === 'string'
602
+ ? { src: item.event.avatar }
603
+ : item.event.avatar;
604
+ const avatar = document.createElement('snice-avatar');
605
+ avatar.className = 'calendar__event-avatar';
606
+ avatar.setAttribute('part', 'event-avatar');
607
+ // Attributes, not property assignments: the avatar's shape/size CSS
608
+ // matches on :host([shape])/:host([size]) attribute selectors.
609
+ avatar.setAttribute('size', 'xs');
610
+ avatar.setAttribute('shape', 'circle');
611
+ // Tiny thumbnail — eager: lazy-load buys nothing at this size and
612
+ // stalls on very tall pages.
613
+ avatar.setAttribute('loading', 'eager');
614
+ if (spec.src)
615
+ avatar.src = spec.src;
616
+ if (spec.name)
617
+ avatar.name = spec.name;
618
+ if (spec.alt)
619
+ avatar.alt = spec.alt;
620
+ bar.appendChild(avatar);
621
+ }
622
+ const titleEl = document.createElement('span');
623
+ titleEl.className = 'calendar__event-title';
624
+ titleEl.textContent = item.event.title;
625
+ bar.appendChild(titleEl);
626
+ // Tooltip: static string, or lazy/rich content from eventTooltip.
627
+ // The native title attribute stays only when no tooltip is configured.
628
+ if (item.event.tooltip || this.eventTooltip) {
629
+ bar.onmouseenter = () => this.showEventTooltip(bar, item.event);
630
+ bar.onmouseleave = () => this.hideEventTooltip();
631
+ }
632
+ else {
633
+ bar.title = item.event.title;
634
+ }
635
+ // Popover: strictly per-event opt-in — without `popover`, a click
636
+ // only dispatches calendar-event-click and no request is issued.
637
+ if (item.event.popover) {
638
+ bar.setAttribute('role', 'button');
639
+ bar.setAttribute('tabindex', '0');
640
+ bar.setAttribute('aria-haspopup', 'dialog');
641
+ bar.onkeydown = (e) => {
642
+ if (e.key === 'Enter' || e.key === ' ') {
643
+ e.preventDefault();
644
+ e.stopPropagation();
645
+ this.openEventPopover(bar, item.event);
646
+ }
647
+ };
648
+ bar.onclick = (e) => {
649
+ this.handleEventClick(item.event, e);
650
+ this.openEventPopover(bar, item.event);
651
+ };
339
652
  }
340
653
  else {
341
- eventsContainer.style.display = 'none';
654
+ bar.onclick = (e) => this.handleEventClick(item.event, e);
342
655
  }
656
+ this.grid.appendChild(bar);
343
657
  }
658
+ }
659
+ hiddenPerDay.forEach((count, i) => {
660
+ if (count === 0)
661
+ return;
662
+ const cell = this.dayCells[i];
663
+ if (!cell)
664
+ return;
665
+ const more = document.createElement('div');
666
+ more.className = 'calendar__more';
667
+ more.textContent = `+${count} more`;
668
+ cell.appendChild(more);
344
669
  });
670
+ // Reserve row height for the lane stack (and the "+N more" chip) so
671
+ // stripes never spill past their week row — every cell in a week shares
672
+ // the reservation, since the grid row is as tall as its tallest cell.
673
+ for (let week = 0; week < weekCount; week++) {
674
+ if (weekLaneCounts[week] === 0)
675
+ continue;
676
+ const weekHasMore = hiddenPerDay
677
+ .slice(week * 7, week * 7 + 7).some(count => count > 0);
678
+ for (let i = week * 7; i < week * 7 + 7; i++) {
679
+ const cell = this.dayCells[i];
680
+ if (!cell)
681
+ continue;
682
+ cell.style.setProperty('--calendar-week-lanes', String(weekLaneCounts[week]));
683
+ if (weekHasMore)
684
+ cell.style.setProperty('--calendar-week-more', '1rem');
685
+ }
686
+ }
345
687
  }
346
688
  goToToday() {
347
689
  this.displayDate = new Date();
@@ -433,6 +775,9 @@ let SniceCalendar = (() => {
433
775
  });
434
776
  }
435
777
  handleDayClick(date) {
778
+ // Display-only calendars: days are not selectable at all.
779
+ if (this.noDaySelect)
780
+ return;
436
781
  if (this.isDisabled(date))
437
782
  return;
438
783
  this.value = date;
@@ -485,13 +830,18 @@ let SniceCalendar = (() => {
485
830
  const weekdayEl = document.createElement('div');
486
831
  weekdayEl.className = 'calendar__weekday';
487
832
  weekdayEl.textContent = day;
833
+ weekdayEl.style.gridRow = '1';
834
+ weekdayEl.style.gridColumn = String(i + 1);
488
835
  // Insert before the first day cell so header row stays at the top
489
836
  this.grid.insertBefore(weekdayEl, this.grid.children[i] || null);
490
837
  });
491
838
  this.updateView();
492
839
  }
493
- });
494
- return _classThis;
840
+ static {
841
+ __runInitializers(_classThis, _classExtraInitializers);
842
+ }
843
+ };
844
+ return SniceCalendar = _classThis;
495
845
  })();
496
846
 
497
847
  export { SniceCalendar };