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.
- package/adapters/react/SniceProvider.js +1 -1
- package/adapters/react/SniceRouter.js +1 -1
- package/adapters/react/avatar.d.ts +1 -0
- package/adapters/react/avatar.d.ts.map +1 -1
- package/adapters/react/avatar.js +1 -1
- package/adapters/react/avatar.js.map +1 -1
- package/adapters/react/avatar.tsx +2 -1
- package/adapters/react/calendar.d.ts +4 -0
- package/adapters/react/calendar.d.ts.map +1 -1
- package/adapters/react/calendar.js +1 -1
- package/adapters/react/calendar.js.map +1 -1
- package/adapters/react/calendar.tsx +5 -1
- package/adapters/react/matchRoute.js +68 -2
- package/adapters/react/matchRoute.js.map +1 -1
- package/adapters/react/route-match.d.ts +7 -0
- package/adapters/react/useRequestHandler.js +1 -1
- package/bin/analyzer-contracts.js +60 -2
- package/bin/project-analyzer.js +1262 -118
- package/bin/snice.js +95 -5
- package/custom-elements.json +112 -0
- package/dist/cdn/accordion/snice-accordion.js +1 -1
- package/dist/cdn/action-bar/snice-action-bar.js +1 -1
- package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
- package/dist/cdn/alert/snice-alert.js +1 -1
- package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
- package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
- package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
- package/dist/cdn/availability/snice-availability.js +1 -1
- package/dist/cdn/avatar/README.md +1 -1
- package/dist/cdn/avatar/snice-avatar.js +9 -3
- package/dist/cdn/avatar/snice-avatar.js.map +1 -1
- package/dist/cdn/avatar/snice-avatar.min.js +2 -2
- package/dist/cdn/avatar/snice-avatar.min.js.map +1 -1
- package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
- package/dist/cdn/badge/snice-badge.js +1 -1
- package/dist/cdn/banner/snice-banner.js +1 -1
- package/dist/cdn/binpack/snice-binpack.js +1 -1
- package/dist/cdn/book/snice-book.js +1 -1
- package/dist/cdn/booking/snice-booking.js +1 -1
- package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
- package/dist/cdn/button/snice-button.js +2 -2
- package/dist/cdn/button/snice-button.js.map +1 -1
- package/dist/cdn/button/snice-button.min.js +1 -1
- package/dist/cdn/button/snice-button.min.js.map +1 -1
- package/dist/cdn/calendar/README.md +2 -2
- package/dist/cdn/calendar/snice-calendar.js +562 -40
- package/dist/cdn/calendar/snice-calendar.js.map +1 -1
- package/dist/cdn/calendar/snice-calendar.min.js +28 -1
- package/dist/cdn/calendar/snice-calendar.min.js.map +1 -1
- package/dist/cdn/camera/snice-camera.js +1 -1
- package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
- package/dist/cdn/candlestick/snice-candlestick.js +1 -1
- package/dist/cdn/card/snice-card.js +1 -1
- package/dist/cdn/carousel/snice-carousel.js +1 -1
- package/dist/cdn/cart/snice-cart.js +1 -1
- package/dist/cdn/chart/snice-chart.js +1 -1
- package/dist/cdn/chat/snice-chat.js +1 -1
- package/dist/cdn/checkbox/snice-checkbox.js +1 -1
- package/dist/cdn/chip/snice-chip.js +1 -1
- package/dist/cdn/code-block/snice-code-block.js +1 -1
- package/dist/cdn/color-display/snice-color-display.js +1 -1
- package/dist/cdn/color-picker/snice-color-picker.js +1 -1
- package/dist/cdn/command-palette/snice-command-palette.js +1 -1
- package/dist/cdn/comments/snice-comments.js +1 -1
- package/dist/cdn/countdown/snice-countdown.js +1 -1
- package/dist/cdn/cropper/snice-cropper.js +1 -1
- package/dist/cdn/data-card/snice-data-card.js +1 -1
- package/dist/cdn/date-picker/snice-date-picker.js +1 -1
- package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
- package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
- package/dist/cdn/diff/snice-diff.js +1 -1
- package/dist/cdn/divider/snice-divider.js +1 -1
- package/dist/cdn/doc/snice-doc.js +1 -1
- package/dist/cdn/draw/snice-draw.js +1 -1
- package/dist/cdn/drawer/snice-drawer.js +1 -1
- package/dist/cdn/empty-state/snice-empty-state.js +1 -1
- package/dist/cdn/estimate/snice-estimate.js +1 -1
- package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
- package/dist/cdn/file-upload/snice-file-upload.js +1 -1
- package/dist/cdn/flip-card/snice-flip-card.js +1 -1
- package/dist/cdn/flow/snice-flow.js +1 -1
- package/dist/cdn/form-layout/snice-form-layout.js +1 -1
- package/dist/cdn/funnel/snice-funnel.js +1 -1
- package/dist/cdn/gantt/snice-gantt.js +1 -1
- package/dist/cdn/gauge/snice-gauge.js +1 -1
- package/dist/cdn/grid/snice-grid.js +1 -1
- package/dist/cdn/heatmap/snice-heatmap.js +1 -1
- package/dist/cdn/image/snice-image.js +1 -1
- package/dist/cdn/input/snice-input.js +1 -1
- package/dist/cdn/invoice/snice-invoice.js +1 -1
- package/dist/cdn/kanban/snice-kanban.js +1 -1
- package/dist/cdn/key-value/snice-key-value.js +1 -1
- package/dist/cdn/kpi/snice-kpi.js +1 -1
- package/dist/cdn/layout/snice-layout.js +1 -1
- package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
- package/dist/cdn/link/snice-link.js +1 -1
- package/dist/cdn/link-preview/snice-link-preview.js +1 -1
- package/dist/cdn/list/snice-list.js +1 -1
- package/dist/cdn/location/snice-location.js +1 -1
- package/dist/cdn/login/README.md +1 -1
- package/dist/cdn/login/snice-login.js +2 -2
- package/dist/cdn/login/snice-login.js.map +1 -1
- package/dist/cdn/login/snice-login.min.js +1 -1
- package/dist/cdn/login/snice-login.min.js.map +1 -1
- package/dist/cdn/map/snice-map.js +1 -1
- package/dist/cdn/markdown/snice-markdown.js +1 -1
- package/dist/cdn/masonry/snice-masonry.js +1 -1
- package/dist/cdn/menu/snice-menu.js +1 -1
- package/dist/cdn/message-strip/snice-message-strip.js +1 -1
- package/dist/cdn/modal/snice-modal.js +1 -1
- package/dist/cdn/music-player/snice-music-player.js +1 -1
- package/dist/cdn/nav/snice-nav.js +1 -1
- package/dist/cdn/network-graph/snice-network-graph.js +1 -1
- package/dist/cdn/notification-center/snice-notification-center.js +1 -1
- package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
- package/dist/cdn/org-chart/snice-org-chart.js +1 -1
- package/dist/cdn/pagination/snice-pagination.js +1 -1
- package/dist/cdn/paint/snice-paint.js +1 -1
- package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
- package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
- package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
- package/dist/cdn/popover/snice-popover.js +1 -1
- package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
- package/dist/cdn/product-card/snice-product-card.js +1 -1
- package/dist/cdn/progress/snice-progress.js +1 -1
- package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
- package/dist/cdn/qr-code/snice-qr-code.js +1 -1
- package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
- package/dist/cdn/radio/snice-radio.js +1 -1
- package/dist/cdn/range-slider/snice-range-slider.js +1 -1
- package/dist/cdn/rating/snice-rating.js +1 -1
- package/dist/cdn/receipt/snice-receipt.js +1 -1
- package/dist/cdn/recipe/snice-recipe.js +1 -1
- package/dist/cdn/runtime/README.md +2 -2
- package/dist/cdn/runtime/snice-runtime.esm.js +706 -267
- package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.js +706 -267
- package/dist/cdn/runtime/snice-runtime.js.map +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js +1 -1
- package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
- package/dist/cdn/sankey/snice-sankey.js +1 -1
- package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
- package/dist/cdn/select/snice-select.js +3 -1
- package/dist/cdn/select/snice-select.js.map +1 -1
- package/dist/cdn/select/snice-select.min.js +2 -2
- package/dist/cdn/select/snice-select.min.js.map +1 -1
- package/dist/cdn/skeleton/snice-skeleton.js +1 -1
- package/dist/cdn/slider/snice-slider.js +1 -1
- package/dist/cdn/sortable/snice-sortable.js +1 -1
- package/dist/cdn/sparkline/snice-sparkline.js +1 -1
- package/dist/cdn/spinner/snice-spinner.js +1 -1
- package/dist/cdn/split-button/snice-split-button.js +1 -1
- package/dist/cdn/split-pane/snice-split-pane.js +1 -1
- package/dist/cdn/spotlight/snice-spotlight.js +1 -1
- package/dist/cdn/stat-group/snice-stat-group.js +1 -1
- package/dist/cdn/step-input/snice-step-input.js +1 -1
- package/dist/cdn/stepper/snice-stepper.js +1 -1
- package/dist/cdn/switch/README.md +1 -1
- package/dist/cdn/switch/snice-switch.js +8 -4
- package/dist/cdn/switch/snice-switch.js.map +1 -1
- package/dist/cdn/switch/snice-switch.min.js +8 -4
- package/dist/cdn/switch/snice-switch.min.js.map +1 -1
- package/dist/cdn/table/README.md +2 -2
- package/dist/cdn/table/snice-table.esm.js +77 -5
- package/dist/cdn/table/snice-table.esm.js.map +1 -1
- package/dist/cdn/table/snice-table.esm.min.js +68 -47
- package/dist/cdn/table/snice-table.esm.min.js.map +1 -1
- package/dist/cdn/table/snice-table.js +76 -4
- package/dist/cdn/table/snice-table.js.map +1 -1
- package/dist/cdn/table/snice-table.min.js +53 -32
- package/dist/cdn/table/snice-table.min.js.map +1 -1
- package/dist/cdn/tabs/snice-tabs.js +1 -1
- package/dist/cdn/tag/snice-tag.js +1 -1
- package/dist/cdn/tag-input/snice-tag-input.js +1 -1
- package/dist/cdn/terminal/snice-terminal.js +1 -1
- package/dist/cdn/testimonial/snice-testimonial.js +1 -1
- package/dist/cdn/textarea/snice-textarea.js +1 -1
- package/dist/cdn/time-picker/snice-time-picker.js +1 -1
- package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
- package/dist/cdn/timeline/snice-timeline.js +1 -1
- package/dist/cdn/timer/snice-timer.js +1 -1
- package/dist/cdn/toast/snice-toast.js +1 -1
- package/dist/cdn/tooltip/snice-tooltip.js +1 -1
- package/dist/cdn/tree/snice-tree.js +1 -1
- package/dist/cdn/treemap/snice-treemap.js +1 -1
- package/dist/cdn/user-card/snice-user-card.js +1 -1
- package/dist/cdn/video-player/snice-video-player.js +1 -1
- package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
- package/dist/cdn/waterfall/snice-waterfall.js +1 -1
- package/dist/cdn/weather/snice-weather.js +1 -1
- package/dist/cdn/work-order/snice-work-order.js +1 -1
- package/dist/components/avatar/snice-avatar.d.ts +1 -0
- package/dist/components/avatar/snice-avatar.js +8 -2
- package/dist/components/avatar/snice-avatar.js.map +1 -1
- package/dist/components/avatar/snice-avatar.types.d.ts +2 -0
- package/dist/components/button/snice-button.js +1 -1
- package/dist/components/button/snice-button.js.map +1 -1
- package/dist/components/calendar/snice-calendar.d.ts +38 -1
- package/dist/components/calendar/snice-calendar.js +390 -40
- package/dist/components/calendar/snice-calendar.js.map +1 -1
- package/dist/components/calendar/snice-calendar.types.d.ts +63 -0
- package/dist/components/select/snice-select.js +2 -0
- package/dist/components/select/snice-select.js.map +1 -1
- package/dist/components/switch/snice-switch.js +7 -3
- package/dist/components/switch/snice-switch.js.map +1 -1
- package/dist/components/table/snice-table.d.ts +9 -0
- package/dist/components/table/snice-table.js +72 -2
- package/dist/components/table/snice-table.js.map +1 -1
- package/dist/components/table/table-keyboard.js +1 -1
- package/dist/components/table/table-keyboard.js.map +1 -1
- package/dist/index.cjs +703 -264
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +703 -264
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +703 -264
- package/dist/index.iife.js.map +1 -1
- package/dist/parts.d.ts +14 -4
- package/dist/react/SniceProvider.js +1 -1
- package/dist/react/SniceRouter.js +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/matchRoute.js +68 -2
- package/dist/react/matchRoute.js.map +1 -1
- package/dist/react/route-match.d.ts +7 -0
- package/dist/react/useRequestHandler.js +1 -1
- package/dist/render-errors.d.ts +9 -0
- package/dist/route-match.d.ts +7 -0
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/template-marker.d.ts +5 -0
- package/dist/testing-dom.cjs +1 -1
- package/dist/testing-dom.esm.js +1 -1
- package/dist/testing.d.ts +3 -0
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/dist/types/dispatch-options.d.ts +5 -4
- package/dist/types/event-timing.d.ts +7 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/on-options.d.ts +21 -6
- package/dist/utils.d.ts +3 -0
- package/docs/ai/DEVELOPMENT.md +1 -1
- package/docs/ai/api.md +7 -2
- package/docs/ai/cli.md +14 -0
- package/docs/ai/components/avatar.md +1 -0
- package/docs/ai/components/calendar.md +24 -1
- package/docs/ai/components/switch.md +3 -0
- package/docs/ai/components/table.md +1 -1
- package/docs/ai/decorators.md +3 -2
- package/docs/ai/events.md +45 -8
- package/docs/ai/rendering.md +7 -0
- package/docs/ai/routing.md +6 -1
- package/docs/ai/testing.md +17 -0
- package/docs/cli.md +19 -0
- package/docs/components/avatar.md +1 -0
- package/docs/components/calendar.md +112 -2
- package/docs/components/switch.md +7 -1
- package/docs/components/table.md +2 -1
- package/docs/events.md +90 -10
- package/docs/rendering.md +10 -0
- package/docs/routing.md +22 -1
- package/docs/testing.md +19 -0
- package/package.json +2 -2
- 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{
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
-
|
|
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
|
-
|
|
840
|
+
static {
|
|
841
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
return SniceCalendar = _classThis;
|
|
495
845
|
})();
|
|
496
846
|
|
|
497
847
|
export { SniceCalendar };
|