@vc-shell/vc-app-skill 2.1.0 → 2.2.0-pr260.a8bd3a7

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 (141) hide show
  1. package/package.json +1 -1
  2. package/runtime/VERSION +1 -1
  3. package/runtime/agents/migration-agent.md +4 -2
  4. package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
  5. package/runtime/knowledge/docs/core/api/platform.docs.md +20 -18
  6. package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +43 -34
  7. package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +5 -3
  8. package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +12 -10
  9. package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +7 -5
  10. package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +8 -6
  11. package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +3 -1
  12. package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +1 -1
  13. package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +8 -5
  14. package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +12 -12
  15. package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +3 -3
  16. package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +4 -3
  17. package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +1 -0
  18. package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +3 -3
  19. package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +5 -4
  20. package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +3 -3
  21. package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +2 -0
  22. package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +1 -2
  23. package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +1 -1
  24. package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +3 -3
  25. package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +1 -0
  26. package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +1 -1
  27. package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +2 -2
  28. package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +2 -1
  29. package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +18 -18
  30. package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +3 -3
  31. package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +10 -7
  32. package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +7 -7
  33. package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +18 -12
  34. package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +2 -2
  35. package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +20 -20
  36. package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +15 -24
  37. package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +2 -2
  38. package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +1 -2
  39. package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +3 -3
  40. package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +19 -18
  41. package/runtime/knowledge/docs/core/notifications/notifications.docs.md +50 -30
  42. package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +30 -11
  43. package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +1 -1
  44. package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +2 -3
  45. package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +26 -26
  46. package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +2 -3
  47. package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +11 -50
  48. package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +9 -6
  49. package/runtime/knowledge/docs/core/services/services.docs.md +15 -13
  50. package/runtime/knowledge/docs/core/types/types.docs.md +37 -40
  51. package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +1 -2
  52. package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +21 -30
  53. package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +2 -2
  54. package/runtime/knowledge/docs/core/utilities/utilities.docs.md +9 -8
  55. package/runtime/knowledge/docs/injection-keys.docs.md +6 -11
  56. package/runtime/knowledge/docs/modules/assets/assets-details.docs.md +7 -7
  57. package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +1 -1
  58. package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +20 -12
  59. package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +10 -10
  60. package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +6 -6
  61. package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +4 -4
  62. package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +16 -14
  63. package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +1 -1
  64. package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +12 -11
  65. package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +10 -3
  66. package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +3 -3
  67. package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +9 -2
  68. package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +4 -2
  69. package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
  70. package/runtime/knowledge/docs/shell/components/notification-dropdown/notification-dropdown.docs.md +35 -31
  71. package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -11
  72. package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +8 -7
  73. package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +23 -21
  74. package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +5 -3
  75. package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +7 -7
  76. package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +11 -11
  77. package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +28 -16
  78. package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +17 -19
  79. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +21 -0
  80. package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +2 -1
  81. package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +2 -2
  82. package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +15 -14
  83. package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +9 -6
  84. package/runtime/knowledge/docs/ui/components/atoms/vc-environment-banner/vc-environment-banner.docs.md +42 -0
  85. package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +1 -1
  86. package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +10 -9
  87. package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +19 -4
  88. package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +2 -2
  89. package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +5 -4
  90. package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +5 -4
  91. package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +9 -8
  92. package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +7 -0
  93. package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +1 -1
  94. package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +2 -2
  95. package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +1 -1
  96. package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +11 -10
  97. package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +28 -8
  98. package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +22 -19
  99. package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +8 -8
  100. package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +16 -6
  101. package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +9 -8
  102. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +42 -34
  103. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +1 -1
  104. package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +14 -1
  105. package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +3 -1
  106. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +34 -33
  107. package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +26 -24
  108. package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +12 -14
  109. package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +30 -30
  110. package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +2 -2
  111. package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +1 -1
  112. package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +34 -31
  113. package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +14 -12
  114. package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +1 -1
  115. package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +36 -27
  116. package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +5 -1
  117. package/runtime/knowledge/docs/ui/components/molecules/{vc-dropdown-panel/vc-dropdown-panel.docs.md → vc-popover/vc-popover.docs.md} +24 -27
  118. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +10 -9
  119. package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +44 -19
  120. package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +11 -11
  121. package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +15 -14
  122. package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +15 -15
  123. package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +15 -13
  124. package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +5 -1
  125. package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +18 -0
  126. package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +48 -78
  127. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +9 -11
  128. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +71 -43
  129. package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +27 -20
  130. package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +2 -2
  131. package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +12 -12
  132. package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +33 -24
  133. package/runtime/knowledge/docs/ui/components/organisms/vc-scheduler/vc-scheduler.docs.md +509 -0
  134. package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +43 -26
  135. package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +15 -9
  136. package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +8 -6
  137. package/runtime/knowledge/docs/ui/composables/useTableSearch.docs.md +3 -3
  138. package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +4 -4
  139. package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +2 -3
  140. package/runtime/knowledge/migration-prompts/table-url-state-migration.md +221 -0
  141. package/runtime/vc-app.md +1 -0
@@ -74,12 +74,14 @@ The `variant` prop adds a semantic icon and color to the popup. Available values
74
74
 
75
75
  When `variant` is anything other than `"default"`, a large icon is rendered to the left of the content area:
76
76
 
77
- | Variant | Icon | Color token |
78
- | --------- | ----------------------- | --------------- |
79
- | `warning` | `lucide-triangle-alert` | `--warning-500` |
80
- | `error` | `lucide-circle-alert` | `--danger-500` |
81
- | `success` | `lucide-circle-check` | `--success-500` |
82
- | `info` | `lucide-info` | `--info-500` |
77
+ | Variant | Icon | Color token (default value) |
78
+ | --------- | ----------------------- | ---------------------------------------------- |
79
+ | `warning` | `lucide-triangle-alert` | `--popup-warning-icon-color` (`--warning-500`) |
80
+ | `error` | `lucide-circle-alert` | `--popup-error-icon-color` (`--danger-500`) |
81
+ | `success` | `lucide-circle-check` | `--popup-success-icon-color` (`--success-500`) |
82
+ | `info` | `lucide-info` | `--popup-info-icon-color` (`--info-500`) |
83
+
84
+ The icon color is overridable per variant via `--popup-<variant>-icon-color`.
83
85
 
84
86
  ### Title
85
87
 
@@ -140,10 +142,9 @@ The `close` event carries a `PopupCloseReason` string so you can react different
140
142
  </VcPopup>
141
143
 
142
144
  <script setup lang="ts">
143
- import type { PopupCloseReason } from "@vc-shell/framework";
144
-
145
- function onClose(reason?: PopupCloseReason) {
146
- // reason is "overlay" | "escape" | "action"
145
+ // The reason is the union `"overlay" | "escape" | "action"`.
146
+ // (`PopupCloseReason` is internal to vc-popup.vue and is not re-exported from the framework entry.)
147
+ function onClose(reason?: "overlay" | "escape" | "action") {
147
148
  if (reason === "action") {
148
149
  // User clicked a button
149
150
  }
@@ -238,10 +239,10 @@ The `modalWidth` prop accepts a Tailwind CSS max-width class. The default is `"t
238
239
 
239
240
  Two props control fullscreen behavior:
240
241
 
241
- | Prop | Effect |
242
- | -------------------- | ----------------------------------------------------------------------- |
243
- | `isFullscreen` | Full viewport on **all** screen sizes |
244
- | `isMobileFullscreen` | Full viewport on **mobile only** (detected via `IsMobileKey` injection) |
242
+ | Prop | Effect |
243
+ | -------------------- | ---------------------------------------------------------------------------- |
244
+ | `isFullscreen` | Full viewport on **all** screen sizes |
245
+ | `isMobileFullscreen` | Full viewport on **mobile only** (detected via `useResponsive()` `isMobile`) |
245
246
 
246
247
  ```vue
247
248
  <VcPopup v-model="open" title="Image Editor" is-fullscreen>
@@ -546,16 +547,24 @@ Or display a richer error popup in-template:
546
547
 
547
548
  ## CSS Custom Properties
548
549
 
549
- | Variable | Default | Description |
550
- | ---------------------------- | ---------------------- | ------------------------------------ |
551
- | `--popup-border-radius` | `6px` | Border radius of the dialog panel |
552
- | `--popup-shadow` | `var(--shadow-md)` | Box shadow around the panel |
553
- | `--popup-overlay-blur` | `var(--overlay-blur)` | Backdrop blur amount |
554
- | `--popup-bg` | `var(--additional-50)` | Background color of the dialog panel |
555
- | `--popup-header-color` | `var(--primary-700)` | Title text color |
556
- | `--popup-content-text-color` | `var(--primary-700)` | Content text color |
557
- | `--popup-footer-separator` | `var(--neutrals-200)` | Footer top border color |
558
- | `--popup-overlay` | `var(--overlay-bg)` | Overlay background color |
550
+ > **Note:** New themes should override `--vc-popup-border-radius`, `--vc-popup-shadow`, and `--vc-popup-overlay-blur`. The `--popup-*` variables below are deprecated aliases kept for backward compatibility (the `--vc-popup-*` vars fall back to them).
551
+
552
+ | Variable | Default | Description |
553
+ | ---------------------------- | -------------------------------------------------------- | ------------------------------------ |
554
+ | `--popup-border-radius` | `6px` | Border radius of the dialog panel |
555
+ | `--popup-shadow` | `var(--shadow-md)` | Box shadow around the panel |
556
+ | `--popup-overlay-blur` | `var(--overlay-blur)` | Backdrop blur amount |
557
+ | `--popup-bg` | `var(--additional-50)` | Background color of the dialog panel |
558
+ | `--popup-header-color` | `var(--primary-700)` | Title text color |
559
+ | `--popup-content-text-color` | `var(--primary-700)` | Content text color |
560
+ | `--popup-footer-separator` | `var(--neutrals-200)` | Footer top border color |
561
+ | `--popup-overlay` | `var(--overlay-bg)` | Overlay background color |
562
+ | `--popup-close-btn-bg` | `var(--neutrals-100)` | Close button (X) background |
563
+ | `--popup-close-btn-bg-hover` | `color-mix(in srgb, var(--popup-close-btn-bg), #000 5%)` | Close button background on hover |
564
+ | `--popup-warning-icon-color` | `var(--warning-500)` | Warning variant icon color |
565
+ | `--popup-error-icon-color` | `var(--danger-500)` | Error variant icon color |
566
+ | `--popup-success-icon-color` | `var(--success-500)` | Success variant icon color |
567
+ | `--popup-info-icon-color` | `var(--info-500)` | Info variant icon color |
559
568
 
560
569
  ## Accessibility
561
570
 
@@ -0,0 +1,509 @@
1
+ ---
2
+ title: VcScheduler
3
+ category: components
4
+ group: data-display
5
+ ---
6
+
7
+ # VcScheduler
8
+
9
+ A calendar organism for planning date-bound periods -- promotions, pricelist windows, campaigns. It defaults to a Month grid where all-day events render as bars (stacking into lanes when they overlap, with a "+N more" overflow popover) and shorter events render as timed chips. It can also switch to a vertical time-grid Timeline (Day or Week) rendering of the same events.
10
+
11
+ ## Quick Start
12
+
13
+ ```vue
14
+ <template>
15
+ <div style="height: 640px">
16
+ <VcScheduler
17
+ v-model:view="view"
18
+ v-model:date="date"
19
+ :events="events"
20
+ editable
21
+ @event-update="onEventUpdate"
22
+ @event-create="onEventCreate"
23
+ />
24
+ </div>
25
+ </template>
26
+
27
+ <script setup lang="ts">
28
+ import { ref } from "vue";
29
+ import { VcScheduler } from "@vc-shell/framework";
30
+ import type { ISchedulerEvent, SchedulerView } from "@vc-shell/framework";
31
+
32
+ const view = ref<SchedulerView>("month");
33
+ const date = ref(new Date());
34
+
35
+ const events = ref<ISchedulerEvent[]>([{ id: "e1", title: "Summer Sale", start: new Date("2026-07-01"), end: new Date("2026-07-06"), allDay: true }]);
36
+
37
+ function onEventUpdate(u: { id: string; start: Date; end: Date; title?: string; allDay?: boolean; color?: string }) {
38
+ const event = events.value.find((e) => e.id === u.id);
39
+ if (event) Object.assign(event, u);
40
+ }
41
+
42
+ function onEventCreate(c: { start: Date; end: Date; allDay: boolean; title: string; color?: string }) {
43
+ events.value.push({ id: crypto.randomUUID(), ...c });
44
+ }
45
+ </script>
46
+ ```
47
+
48
+ `VcScheduler` needs an explicit height from its parent -- it fills `height: 100%` internally but does not impose one of its own.
49
+
50
+ ## Table of Contents
51
+
52
+ 1. [Views](#views)
53
+ 2. [Event Model](#event-model)
54
+ 3. [Editable Events](#editable-events)
55
+ 4. [Editing UX: Quick-Create Popover and Editor Modal](#editing-ux-quick-create-popover-and-editor-modal)
56
+ 5. [Recurring Events](#recurring-events)
57
+ 6. [Overlapping Events and Overflow](#overlapping-events-and-overflow)
58
+ 7. [Custom Slots](#custom-slots)
59
+ 8. [Timeline View](#timeline-view)
60
+ 9. [Props](#props)
61
+ 10. [Events](#events)
62
+ 11. [Slots](#slots)
63
+ 12. [CSS Custom Properties](#css-custom-properties)
64
+ 13. [Recipes](#recipes)
65
+ 14. [Common Mistakes](#common-mistakes)
66
+ 15. [Accessibility](#accessibility)
67
+ 16. [Related Components](#related-components)
68
+
69
+ ---
70
+
71
+ ## Views
72
+
73
+ `view` selects the active calendar view and defaults to `"month"`. Bind it with `v-model:view` so the built-in toolbar's view switcher stays in sync with your state:
74
+
75
+ ```vue
76
+ <VcScheduler v-model:view="view" v-model:date="date" :events="events" />
77
+ ```
78
+
79
+ | View | Data props | Description |
80
+ | ----------------- | ---------- | -------------------------------------------------------------------------------------------------- |
81
+ | `"month"` | `events` | Default. A 6-week grid; all-day events as bars, short events as chips. |
82
+ | `"timeline-day"` | `events` | The same events on a vertical hour grid for one focused day. See [Timeline View](#timeline-view). |
83
+ | `"timeline-week"` | `events` | The same events on a vertical hour grid across 7 day columns. See [Timeline View](#timeline-view). |
84
+
85
+ `date` is the focused date (which month is shown, or the timeline's focused day/week). Bind it with `v-model:date` so the toolbar's prev/next/today controls update your state:
86
+
87
+ ```vue
88
+ <VcScheduler v-model:date="date" :events="events" />
89
+ ```
90
+
91
+ All three views render the same `events` array -- switching `view` only changes how they're laid out (month grid vs. vertical time grid), never which data prop is read.
92
+
93
+ By default only **Month** is offered and the toolbar's view switcher is hidden -- the hour-granular timelines are opt-in, best suited to intraday/timed scheduling rather than the multi-day promo/pricelist norm. Pass the `views` prop to expose them (order preserved; the switcher appears once more than one view is listed):
94
+
95
+ ```vue
96
+ <VcScheduler :views="['month', 'timeline-day', 'timeline-week']" :events="events" />
97
+ ```
98
+
99
+ ## Event Model
100
+
101
+ ```ts
102
+ interface ISchedulerEvent {
103
+ id: string;
104
+ start: Date;
105
+ end: Date;
106
+ title: string;
107
+ /** Forces bar (true) or chip (false) rendering. Inferred from duration when omitted. */
108
+ allDay?: boolean;
109
+ /** Optional explicit color (CSS color or var()). Omit it and the event is auto-colored:
110
+ * a deterministic palette color is derived from the title at render time (same title →
111
+ * same color, recurring occurrences included), so you never store colors. Set this only
112
+ * to override. The editor's manual Color field is hidden unless `allow-color` is set. */
113
+ color?: string;
114
+ /** Per-event override of the global `editable` prop. */
115
+ editable?: boolean;
116
+ /** Free-form data for custom slots/handlers. */
117
+ meta?: Record<string, unknown>;
118
+ /** RRULE string on a master event, e.g. "FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU;COUNT=10". */
119
+ recurrence?: string;
120
+ /** Occurrence start dates removed from the master series. */
121
+ exceptionDates?: Date[];
122
+ /** On an override event: id of the master series it belongs to. */
123
+ recurrenceId?: string;
124
+ /** On an override event: the original occurrence start it replaces. */
125
+ originalStart?: Date;
126
+ }
127
+ ```
128
+
129
+ An event renders as a full-width **bar** spanning its day columns when `allDay` is `true`, or when omitted and `end - start >= 24h`. Anything shorter renders as a compact **chip** showing `HH:mm` plus the title, listed under its day cell.
130
+
131
+ The last four fields (`recurrence`, `exceptionDates`, `recurrenceId`, `originalStart`) only matter for recurring series -- see [Recurring Events](#recurring-events).
132
+
133
+ ## Editable Events
134
+
135
+ Set `editable` to allow drag-to-move and drag-to-resize on existing event bars, and to enable creating new events by clicking or dragging on an empty cell. Moves and resizes commit on pointer-up via `event-update`; empty-cell interactions open the built-in quick-create popover or editor modal, which commit via `event-create` -- see [Editing UX](#editing-ux-quick-create-popover-and-editor-modal) for the full interaction model.
136
+
137
+ ```vue
138
+ <VcScheduler v-model:date="date" :events="events" editable @event-update="onEventUpdate" @event-create="onEventCreate" />
139
+ ```
140
+
141
+ To make only _some_ events editable, use `isEventEditable` -- it is re-evaluated on every render, so an inline arrow function is safe:
142
+
143
+ ```vue
144
+ <VcScheduler :events="events" editable :is-event-editable="(e) => e.meta?.locked !== true" />
145
+ ```
146
+
147
+ An event can also opt out individually via its own `editable: false` field, independent of the global prop.
148
+
149
+ ## Editing UX: Quick-Create Popover and Editor Modal
150
+
151
+ With `editable`, `VcScheduler` ships a complete built-in create/edit flow -- no host-side modal wiring required:
152
+
153
+ | Gesture | Result |
154
+ | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
155
+ | Toolbar **"+ New event"** button | Opens the **editor modal** (create mode) for an all-day event on the focused date. Shown whenever `editable`. |
156
+ | Single click on an empty cell | Opens the **quick-create popover**, anchored to the cell, with a title field. |
157
+ | Double click on an empty cell | Opens the **editor modal** directly (create mode) -- richer fields, no popover. |
158
+ | Drag across empty cells | Opens the **editor modal** (create mode) pre-filled with the dragged range. |
159
+ | Click an existing event | Opens the built-in quick-info popover (unless `quickInfo` is `false`): a color-tinted header with the title, the date/time, a human-readable recurrence summary for recurring events, an optional category line from `meta.category`/`meta.description`, and Edit/Delete. |
160
+ | Quick-info popover's "Edit" button | Opens the **editor modal** (edit mode), pre-filled from the event. |
161
+ | Quick-create popover's "More options" | Opens the **editor modal** (create mode), carrying over the typed title. |
162
+
163
+ The editor modal additionally exposes all-day toggle, start/end date-time, and color, plus a Delete action in edit mode (commits via `event-delete`). Saving from either surface emits the public `event-create`/`event-update` event -- see [Events](#events) for the exact payloads.
164
+
165
+ This entire flow is internal state: no `v-model` or extra event wiring is needed to make it work, beyond `editable` and the `event-create`/`event-update`/`event-delete` handlers you already have for persisting the result.
166
+
167
+ ### `editorMode`: opting out of the built-in UI
168
+
169
+ Set `editorMode="emit"` to skip the quick-create popover and editor modal entirely and drive your own create/edit UI instead. In this mode:
170
+
171
+ - A create gesture (any of the rows above) emits `event-create` directly with an empty `title`, instead of opening a popover/modal.
172
+ - Clicking an event's quick-info "Edit" button emits `event-edit` with the full event, instead of opening the editor modal. (`event-edit` never fires in the default `"builtin"` mode.)
173
+
174
+ ```vue
175
+ <VcScheduler :events="events" editable editor-mode="emit" @event-create="openMyCreateDialog" @event-edit="openMyEditDialog" />
176
+ ```
177
+
178
+ ### Customizing the built-in surfaces: `#quick-create` and `#event-editor`
179
+
180
+ To keep the built-in orchestration (state, anchoring, intent handling) but swap in your own markup, override the `#quick-create` and/or `#event-editor` slots:
181
+
182
+ ```vue
183
+ <VcScheduler :events="events" editable>
184
+ <template #quick-create="{ open, anchorRect, draft, save, more, close }">
185
+ <MyQuickCreate :open="open" :anchor-rect="anchorRect" :draft="draft" @save="save" @more="more" @close="close" />
186
+ </template>
187
+ <template #event-editor="{ open, mode, draft, save, delete: onDelete, close }">
188
+ <MyEventEditor :open="open" :mode="mode" :draft="draft" @save="save" @delete="onDelete" @close="close" />
189
+ </template>
190
+ </VcScheduler>
191
+ ```
192
+
193
+ | Slot | Scope | Description |
194
+ | -------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
195
+ | `quick-create` | `{ open, anchorRect, draft, save, more, close }` | Replaces the quick-create popover. `save({ title })` commits; `more({ title })` should route into your editor. |
196
+ | `event-editor` | `{ open, mode, draft, save, delete, close }` | Replaces the editor modal. `mode` is `"create"` \| `"edit"`; `save(draft)` commits; `delete({ id })` removes. |
197
+
198
+ `draft` is an `IEventDraft` (`{ id?, title, start, end, allDay, color? }`) -- the working copy being created or edited.
199
+
200
+ ## Recurring Events
201
+
202
+ An event with a non-empty `recurrence` field is a **master**: `recurrence` is a bare [RRULE](https://icalendar.org/iCalendar-RFC-5545/3-3-10-recurrence-rule.html) string (e.g. `"FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=8"`) and the master's own `start`/`end` act as `DTSTART`/duration. `VcScheduler` expands each master into concrete **occurrences** for whatever window the active view renders -- occurrences are synthesized, not stored, and carry a "↻" marker (Month bar/chip, Timeline bar, mobile agenda row) so they're visually distinguishable from one-off events.
203
+
204
+ Occurrences are **not limited to a single day**: the master's `start`->`end` duration is preserved for every occurrence, so a multi-day master (all-day or timed) yields multi-day occurrences that render as spanning bars. For example, an all-day master `start: Fri 00:00`, `end: Mon 00:00` with `FREQ=WEEKLY;BYDAY=FR` repeats a 3-day Fri->Sun span every week (see the `RecurringMultiDay` story).
205
+
206
+ This is an **iCal-style storage model** -- your `events` array holds only masters and overrides, never the expanded occurrences:
207
+
208
+ - **Master**: one event with `recurrence` set. Its own `start`/`end` is also the first occurrence.
209
+ - **Exception dates**: `exceptionDates` on the master lists occurrence start times to skip entirely -- no occurrence is synthesized for them, and no override is required.
210
+ - **Override**: a separate, ordinary event (no `recurrence` of its own) with `recurrenceId` set to the master's `id` and `originalStart` set to the occurrence start it replaces. Any other field (`title`, `start`, `end`, `color`, ...) can differ from the synthesized occurrence -- this is how a single instance of a series gets moved, retitled, or recolored without touching the rest of the series.
211
+
212
+ ```ts
213
+ const master: ISchedulerEvent = {
214
+ id: "m1",
215
+ title: "Weekly Pricing Sync",
216
+ start: new Date("2026-07-01T09:00:00"),
217
+ end: new Date("2026-07-01T10:00:00"),
218
+ recurrence: "FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=8",
219
+ exceptionDates: [new Date("2026-07-08T09:00:00")], // that Wednesday is skipped
220
+ };
221
+
222
+ const override: ISchedulerEvent = {
223
+ id: "o1",
224
+ title: "Pricing Sync (moved to afternoon)",
225
+ start: new Date("2026-07-13T14:00:00"),
226
+ end: new Date("2026-07-13T15:00:00"),
227
+ recurrenceId: "m1",
228
+ originalStart: new Date("2026-07-13T09:00:00"), // the occurrence it replaces
229
+ };
230
+ ```
231
+
232
+ ### Creating/editing recurrence: the editor's Repeat form
233
+
234
+ The built-in editor modal (see [Editing UX](#editing-ux-quick-create-popover-and-editor-modal)) exposes a **Repeat** field when creating a new event or editing a master's "All events" scope (see below): `None` / `Daily` / `Weekly` / `Monthly` / `Yearly`, an **every N** interval, weekday toggles (`Weekly` only, multi-select), and an **End** setting (`Never`, `After N occurrences`, or `On` a specific date). The editor bridges this form to/from the stored `recurrence` RRULE string -- hosts never construct or parse RRULE text themselves.
235
+
236
+ ### Editing or deleting an occurrence: the This event / All events prompt
237
+
238
+ Clicking **Edit** or **Delete** on a recurring occurrence (in the quick-info popover or elsewhere) opens a scope dialog asking **This event** or **All events** before doing anything else:
239
+
240
+ | Action | Scope | Effect |
241
+ | ------ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
242
+ | Edit | **This event** | Opens the editor for just that occurrence, with no recurrence field (an override isn't itself recurring). Saving creates or updates an override -- only that occurrence changes. |
243
+ | Edit | **All events** | Opens the editor pre-filled with the master's own fields and recurrence rule. Saving updates the master -- every occurrence reflects the change. |
244
+ | Delete | **This event** | Adds the occurrence's date to the master's `exceptionDates` and removes its override, if any -- only that occurrence disappears. |
245
+ | Delete | **All events** | Deletes the master itself -- the whole series (and any of its overrides) disappears. |
246
+
247
+ This scope choice only appears for occurrences of a recurring series (`recurrenceId` set); plain events and masters/overrides edited directly are unaffected.
248
+
249
+ ### Extended `event-create` / `event-update` payloads
250
+
251
+ Recurrence routes through the same `event-create`/`event-update`/`event-delete` events already used for plain events (see [Events](#events)), with additional optional fields:
252
+
253
+ - `event-create` gains `recurrence?: string` (creating a new recurring master) and `recurrenceId?: string` / `originalStart?: Date` (creating a first-time override for a "This event" edit).
254
+ - `event-update` gains `recurrence?: string` (an "All events" edit changing the rule), `exceptionDates?: Date[]` (a "This event" delete), and `recurrenceId?: string` / `originalStart?: Date` (updating an existing override).
255
+
256
+ A host persisting events must apply these the same way the master/override model expects -- merge `event-update` onto the event matching `id`, and for `event-create`, push a master when `recurrence` is set or an override when `recurrenceId` is set. See the `RecurringEvents` story for a complete, working example of both.
257
+
258
+ ### Out of scope
259
+
260
+ - **"This and following"** scope (edit/delete from an occurrence forward) -- only "This event" and "All events" are supported.
261
+ - **Advanced RRULE features** such as `BYSETPOS` or nth-weekday-of-month (e.g. "2nd Tuesday") -- the editor's Repeat form only produces `FREQ`/`INTERVAL`/`BYDAY`/`COUNT`/`UNTIL`.
262
+ - **`TZID`/timezone-aware recurrence** -- `recurrence` is evaluated against the master's own `start`/`end` as plain `Date` values, with no timezone conversion.
263
+ - **Dragging an occurrence** to move or resize it -- Month/Timeline drag-to-move/resize targets an event by `id`, and a synthesized occurrence has no `id` of its own in `events`; use the This event/All events edit flow instead.
264
+
265
+ ## Overlapping Events and Overflow
266
+
267
+ All-day events that overlap in time on the same days are packed into separate stacked lanes automatically -- no configuration needed. When a day would need more lanes than fit, the extra events collapse into a "+N more" link; clicking it opens a popover listing every all-day event on that date.
268
+
269
+ ## Custom Slots
270
+
271
+ Override event content or the entire toolbar without losing built-in interaction:
272
+
273
+ ```vue
274
+ <VcScheduler v-model:view="view" v-model:date="date" :events="events">
275
+ <template #event="{ event }">
276
+ <strong>{{ event.title }}</strong>
277
+ </template>
278
+ <template #toolbar="{ title, view }">
279
+ <div>{{ title }} -- {{ view }}</div>
280
+ </template>
281
+ </VcScheduler>
282
+ ```
283
+
284
+ The `event` and `event-popover` slots work identically in Timeline view; `empty` is Timeline-only, shown when no events fall in the visible window -- see [Timeline View](#timeline-view).
285
+
286
+ ## Timeline View
287
+
288
+ Set `view` to `"timeline-day"` or `"timeline-week"` to render the same `events` array on a vertical time grid (hours down the Y axis, days across the X axis) instead of the Month grid -- no separate data props, and no `resources`/`bars` model. Switch views from the built-in toolbar (Month | Timeline Day | Timeline Week), or drive `view` directly:
289
+
290
+ ```vue
291
+ <VcScheduler v-model:view="view" v-model:date="date" :events="events" />
292
+ ```
293
+
294
+ - **Timeline Day** shows one focused day (`date`) as a single vertical hour column.
295
+ - **Timeline Week** shows 7 day columns starting from `firstDayOfWeek` over a shared hour axis -- all 7 fit on screen, no horizontal scrolling.
296
+
297
+ Both render day header(s) with an hour gutter down the left, and scroll vertically on mount to the first event (or the working hours). Timed events are placed by their exact start/end time and split into side-by-side lanes when they overlap; all-day / multi-day events sit in a spanning strip above the grid (a single-day column can't represent a multi-day span). Clicking an event opens the same quick-info popover as Month view (unless `quickInfo` is `false`). When today is in view (and within the shown hour range), a thin red **current-time line** is drawn in the today column, updated each minute.
298
+
299
+ Narrow the rendered hour range with `dayStartHour`/`dayEndHour` (default `0`/`24`), e.g. to show only an 8 AM-8 PM business-hours window:
300
+
301
+ ```vue
302
+ <VcScheduler view="timeline-day" :events="events" :day-start-hour="8" :day-end-hour="20" />
303
+ ```
304
+
305
+ The `empty` slot replaces the placeholder shown when no events fall in the visible window.
306
+
307
+ See the [Timeline recipe](#timeline-business-hours-review) below for a full example.
308
+
309
+ ## Props
310
+
311
+ | Prop | Type | Default | Description |
312
+ | ----------------- | --------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
313
+ | `events` | `ISchedulerEvent[]` | `[]` | Events to render, in all views. |
314
+ | `view` | `SchedulerView` | `"month"` | Active view (`"month"` \| `"timeline-day"` \| `"timeline-week"`). Bind with `v-model:view`. |
315
+ | `date` | `Date` | `new Date()` | Focused date -- the month shown (Month), or the focused day/week (Timeline). Bind with `v-model:date`. |
316
+ | `editable` | `boolean` | `false` | Enables drag-to-move / drag-to-resize on events, and click/drag-to-create on empty cells. |
317
+ | `firstDayOfWeek` | `number` | `1` | First column of the Month grid, or first day of a Timeline Week (0 = Sunday, 1 = Monday). |
318
+ | `isEventEditable` | `(e: ISchedulerEvent) => boolean` | `undefined` | Per-event override of `editable`. Re-evaluated every render. |
319
+ | `quickInfo` | `boolean` | `true` | Opens the built-in quick-info popover on event click. Disable for a fully custom click flow. |
320
+ | `dayStartHour` | `number` | `0` | Timeline views. First rendered hour column (0-23). |
321
+ | `dayEndHour` | `number` | `24` | Timeline views. Last rendered hour column, exclusive (1-24). |
322
+ | `editorMode` | `"builtin"` \| `"emit"` | `"builtin"` | `"builtin"` opens the quick-create popover / editor modal for create and edit. `"emit"` skips both and re-emits the intent as `event-create`/`event-edit` instead. See [Editing UX](#editing-ux-quick-create-popover-and-editor-modal). |
323
+ | `loading` | `boolean` | `false` | Async loading. With no events yet, shows a view-shaped skeleton; while events already exist (a refresh), shows a loading overlay over the current content. Override the skeleton via the `#loading` slot. |
324
+
325
+ ## Events
326
+
327
+ | Event | Payload | Description |
328
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
329
+ | `update:view` | `SchedulerView` | Fires when the toolbar's view switcher changes the active view. |
330
+ | `update:date` | `Date` | Fires when the toolbar's prev/next/today controls change the focused date. |
331
+ | `event-click` | `ISchedulerEvent` | Fires when an event bar or chip is activated (click or Enter), in any view. |
332
+ | `event-create` | `{ start: Date; end: Date; allDay: boolean; title: string; color?: string; recurrence?: string; recurrenceId?: string; originalStart?: Date }` | Fires when the quick-create popover or editor modal (create mode) is saved, in any view. `recurrence` is set for a new recurring master; `recurrenceId`/`originalStart` for a new occurrence override -- see [Recurring Events](#recurring-events). |
333
+ | `event-update` | `{ id: string; start: Date; end: Date; title?: string; allDay?: boolean; color?: string; recurrence?: string; exceptionDates?: Date[]; recurrenceId?: string; originalStart?: Date }` | Fires after a drag-move/drag-resize commits, or the editor modal (edit mode) is saved, in any view. The recurrence fields are only set by the This event/All events flow -- see [Recurring Events](#recurring-events). |
334
+ | `event-edit` | `ISchedulerEvent` | Only in `editorMode="emit"`: fires when the quick-info popover's "Edit" button is clicked, instead of opening the built-in editor. |
335
+ | `event-delete` | `{ id: string }` | Fires when the quick-info popover's "Delete" button, or the editor modal's "Delete" button, is clicked. |
336
+
337
+ ## Slots
338
+
339
+ | Slot | Scope | Description |
340
+ | --------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
341
+ | `event` | `{ event }` | Replaces an event's inner content, in any view. Defaults to `event.title`. |
342
+ | `toolbar` | `{ title, view }` | Replaces the entire built-in toolbar. |
343
+ | `event-popover` | `{ event, close }` | Replaces the built-in quick-info popover's content, in any view. |
344
+ | `quick-create` | `{ open, anchorRect, draft, save, more, close }` | Replaces the built-in quick-create popover. See [Editing UX](#editing-ux-quick-create-popover-and-editor-modal). |
345
+ | `event-editor` | `{ open, mode, draft, save, delete, close }` | Replaces the built-in editor modal. See [Editing UX](#editing-ux-quick-create-popover-and-editor-modal). |
346
+ | `empty` | -- | Timeline view. Replaces the empty-state shown when no events are in view. |
347
+ | `loading` | -- | Replaces the built-in first-load skeleton (shown when `loading` and no events yet). |
348
+
349
+ ## CSS Custom Properties
350
+
351
+ | Property | Default | Description |
352
+ | -------------------------- | --------------------- | --------------------------------------------------------------- |
353
+ | `--scheduler-border-color` | `var(--neutrals-200)` | Border color for the grid, header, and row separators. |
354
+ | `--vc-scheduler-event-ink` | `#fff` | Text color on Month-view event bars/chips. |
355
+ | `--z-critical-popup` | (theme z-index scale) | Stacking context for the "+N more" overflow popover. |
356
+ | `--z-local-sticky` | (theme z-index scale) | Timeline view. Stacking context for the sticky two-tier header. |
357
+
358
+ Event fill color comes from `color` (any CSS color or `var(...)` reference) and defaults to `var(--primary-500)`. Event label text is white by default -- see [Common Mistakes](#common-mistakes).
359
+
360
+ ## Recipes
361
+
362
+ ### Month: promotions calendar with drag-to-create
363
+
364
+ ```vue
365
+ <template>
366
+ <div style="height: 640px">
367
+ <VcScheduler
368
+ v-model:date="date"
369
+ :events="promotions"
370
+ editable
371
+ :is-event-editable="(e) => !lockedIds.has(e.id)"
372
+ @event-update="onEventUpdate"
373
+ @event-create="onEventCreate"
374
+ @event-click="(e) => (selectedPromotion = e)"
375
+ />
376
+ </div>
377
+ </template>
378
+
379
+ <script setup lang="ts">
380
+ import { ref } from "vue";
381
+ import { VcScheduler } from "@vc-shell/framework";
382
+ import type { ISchedulerEvent } from "@vc-shell/framework";
383
+
384
+ const date = ref(new Date("2026-07-01"));
385
+
386
+ const promotions = ref<ISchedulerEvent[]>([
387
+ { id: "p1", title: "Summer Sale", start: new Date("2026-07-01"), end: new Date("2026-07-14"), allDay: true },
388
+ { id: "p2", title: "Loyalty pricing review", start: new Date("2026-07-15T09:00:00"), end: new Date("2026-07-15T10:00:00") },
389
+ ]);
390
+
391
+ const lockedIds = new Set(["p1"]);
392
+ const selectedPromotion = ref<ISchedulerEvent | null>(null);
393
+
394
+ function onEventUpdate(u: { id: string; start: Date; end: Date; title?: string; allDay?: boolean; color?: string }) {
395
+ const promo = promotions.value.find((p) => p.id === u.id);
396
+ if (promo) Object.assign(promo, u);
397
+ }
398
+
399
+ function onEventCreate(c: { start: Date; end: Date; allDay: boolean; title: string; color?: string }) {
400
+ promotions.value.push({ id: crypto.randomUUID(), ...c });
401
+ }
402
+ </script>
403
+ ```
404
+
405
+ ### Timeline: business-hours review
406
+
407
+ ```vue
408
+ <template>
409
+ <div style="height: 500px">
410
+ <VcScheduler
411
+ view="timeline-day"
412
+ v-model:date="date"
413
+ :events="reviews"
414
+ :day-start-hour="8"
415
+ :day-end-hour="20"
416
+ editable
417
+ @event-update="onEventUpdate"
418
+ @event-click="(e) => (selectedReview = e)"
419
+ />
420
+ </div>
421
+ </template>
422
+
423
+ <script setup lang="ts">
424
+ import { ref } from "vue";
425
+ import { VcScheduler } from "@vc-shell/framework";
426
+ import type { ISchedulerEvent } from "@vc-shell/framework";
427
+
428
+ const date = ref(new Date(2026, 6, 15));
429
+
430
+ const reviews = ref<ISchedulerEvent[]>([
431
+ { id: "r1", title: "Pricing sync", start: new Date("2026-07-15T09:00:00"), end: new Date("2026-07-15T10:00:00") },
432
+ { id: "r2", title: "Loyalty review", start: new Date("2026-07-15T14:00:00"), end: new Date("2026-07-15T15:00:00") },
433
+ ]);
434
+
435
+ const selectedReview = ref<ISchedulerEvent | null>(null);
436
+
437
+ function onEventUpdate(u: { id: string; start: Date; end: Date; title?: string; allDay?: boolean; color?: string }) {
438
+ const review = reviews.value.find((r) => r.id === u.id);
439
+ if (review) Object.assign(review, u);
440
+ }
441
+ </script>
442
+ ```
443
+
444
+ ## Common Mistakes
445
+
446
+ ### 1. Passing `isEventEditable` as a value instead of a getter function
447
+
448
+ ```vue
449
+ <!-- WRONG: evaluates once, becomes a static boolean-ish value -->
450
+ <VcScheduler :is-event-editable="someEvent.editable" ... />
451
+
452
+ <!-- CORRECT: pass a function; it is called per-event and re-evaluated on every interaction -->
453
+ <VcScheduler :is-event-editable="(e) => e.meta?.locked !== true" ... />
454
+ ```
455
+
456
+ ### 2. Using a light CSS-variable event color
457
+
458
+ Bar/label ink is chosen automatically from the fill's luminance (near-white or near-black, whichever gives higher WCAG contrast), so a **hex** `color` — light or dark — always gets a legible label. The one gap: a **CSS-variable** fill (e.g. `var(--primary-300)`) can't be measured at runtime, so it falls back to white ink; a light var then fails contrast. Past events render as a pale tint of the fill with dark text (also AA), so this only affects live events with a light var fill.
459
+
460
+ ```vue
461
+ <!-- WRONG: a light CSS-var fill can't be measured, falls back to white ink -->
462
+ <script setup>
463
+ const events = [{ id: "a", title: "Promo", start, end, allDay: true, color: "var(--primary-300)" }];
464
+ </script>
465
+
466
+ <!-- CORRECT: use a hex (auto ink handles it), a dark var, or omit color for the auto palette. -->
467
+ <script setup>
468
+ const events = [{ id: "a", title: "Promo", start, end, allDay: true, color: "#a21caf" }];
469
+ </script>
470
+ ```
471
+
472
+ ### 3. Using `view`/`date` as one-way props and expecting the toolbar to work
473
+
474
+ ```vue
475
+ <!-- WRONG: :view/:date without v-model -- the toolbar's prev/next/today and
476
+ view-switch controls emit update:view/update:date, but nothing listens -->
477
+ <VcScheduler :view="view" :date="date" :events="events" />
478
+
479
+ <!-- CORRECT -->
480
+ <VcScheduler v-model:view="view" v-model:date="date" :events="events" />
481
+ ```
482
+
483
+ ### 4. Forgetting to give the container a height
484
+
485
+ ```vue
486
+ <!-- WRONG: no height -- the grid/scroll container collapses to 0px -->
487
+ <VcScheduler :events="events" />
488
+
489
+ <!-- CORRECT: wrap in (or size) a container with an explicit height -->
490
+ <div style="height: 640px">
491
+ <VcScheduler :events="events" />
492
+ </div>
493
+ ```
494
+
495
+ ## Accessibility
496
+
497
+ - The Month grid uses `role="grid"` / `role="row"` / `role="gridcell"` / `role="columnheader"` for the weekday header and day cells, each `gridcell` carrying a full formatted-date `aria-label`.
498
+ - Each event bar and timed chip is a focusable `role="button"` element (`tabindex="0"`) with an `aria-label` built from its title and formatted start/end dates -- activate with click or `Enter`.
499
+ - The "+N more" overflow popover uses `role="dialog"` with an `aria-label` set to the formatted date.
500
+ - The built-in quick-create popover and editor modal reuse `VcPopover`/`VcPopup` respectively, so they inherit those components' accessible naming, focus trapping, and Escape-to-close behavior.
501
+ - The This event/All events scope dialog is a titled `VcPopup` as well. The recurrence editor's weekday toggle buttons expose `aria-pressed` (selected state) and an `aria-label` with the full weekday name, since their visible narrow labels ("S", "M", "T", ...) collide (Sun/Sat, Tue/Thu). The "↻" recurring-occurrence marker is `aria-hidden` -- purely visual, redundant with the event's own accessible name.
502
+ - The toolbar's prev/next buttons carry an explicit `aria-label` ("Previous" / "Next") since they are icon-only; the today/view-switch buttons show text labels.
503
+ - Event move/resize (Month view's `editable`) is a pointer-drag interaction with no keyboard equivalent yet; use a form outside VcScheduler for keyboard-only date edits. Timeline view is read-only (click still opens the quick-info popover).
504
+ - Respects `prefers-reduced-motion` -- event/bar transitions and chip hover transitions are disabled.
505
+
506
+ ## Related Components
507
+
508
+ - [VcDataTable](../vc-data-table/) -- for tabular (non-calendar) views of the same periods.
509
+ - [VcGallery](../vc-gallery/) -- another organism with drag interaction, for image reordering rather than time-based events.