@flux-ui/components 3.0.0-next.57 → 3.0.0-next.59

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 (306) hide show
  1. package/dist/component/FluxButtonStack.vue.d.ts +1 -1
  2. package/dist/component/FluxCalendar.vue.d.ts +63 -2
  3. package/dist/component/{FluxCalendarEvent.vue.d.ts → FluxCalendarItem.vue.d.ts} +9 -7
  4. package/dist/component/FluxClickablePane.vue.d.ts +1 -1
  5. package/dist/component/FluxDivider.vue.d.ts +1 -1
  6. package/dist/component/FluxFilter.vue.d.ts +1 -1
  7. package/dist/component/FluxFilterBar.vue.d.ts +1 -1
  8. package/dist/component/FluxFormInput.vue.d.ts +2 -2
  9. package/dist/component/FluxFormInputAddition.vue.d.ts +1 -1
  10. package/dist/component/FluxFormTreeViewSelect.vue.d.ts +3 -3
  11. package/dist/component/FluxGallery.vue.d.ts +1 -1
  12. package/dist/component/FluxInfo.vue.d.ts +1 -1
  13. package/dist/component/FluxKanban.vue.d.ts +17 -5
  14. package/dist/component/FluxKanbanColumn.vue.d.ts +13 -2
  15. package/dist/component/{FluxKanbanCard.vue.d.ts → FluxKanbanItem.vue.d.ts} +2 -1
  16. package/dist/component/FluxMenuItem.vue.d.ts +1 -1
  17. package/dist/component/FluxNotice.vue.d.ts +1 -1
  18. package/dist/component/FluxPaneHeader.vue.d.ts +1 -1
  19. package/dist/component/FluxPressable.vue.d.ts +1 -1
  20. package/dist/component/FluxPrompt.vue.d.ts +3 -3
  21. package/dist/component/FluxSplitButton.vue.d.ts +1 -1
  22. package/dist/component/FluxStack.vue.d.ts +1 -1
  23. package/dist/component/FluxTab.vue.d.ts +1 -1
  24. package/dist/component/FluxTabBar.vue.d.ts +4 -1
  25. package/dist/component/FluxTabs.vue.d.ts +4 -1
  26. package/dist/component/FluxTimelineItem.vue.d.ts +1 -1
  27. package/dist/component/calendar/FluxCalendarItemDisplay.vue.d.ts +9 -0
  28. package/dist/component/calendar/FluxCalendarMonthView.vue.d.ts +19 -0
  29. package/dist/component/calendar/FluxCalendarTimeGridView.vue.d.ts +36 -0
  30. package/dist/component/calendar/index.d.ts +3 -0
  31. package/dist/component/index.d.ts +2 -2
  32. package/dist/component/primitive/DialogLayout.vue.d.ts +1 -1
  33. package/dist/component/primitive/SelectBase.vue.d.ts +3 -3
  34. package/dist/composable/index.d.ts +3 -0
  35. package/dist/composable/private/index.d.ts +5 -8
  36. package/dist/composable/private/useAsyncFilterOptions.d.ts +1 -1
  37. package/dist/composable/private/useKanban.d.ts +14 -4
  38. package/dist/composable/private/useKanbanAutoScroll.d.ts +13 -0
  39. package/dist/composable/useCalendarInjection.d.ts +2 -0
  40. package/dist/composable/useKanbanInjection.d.ts +2 -0
  41. package/dist/composable/useTabBarInjection.d.ts +2 -0
  42. package/dist/data/di.d.ts +80 -9
  43. package/dist/data/i18n.d.ts +4 -0
  44. package/dist/index.css +1603 -1204
  45. package/dist/index.js +4567 -2819
  46. package/dist/index.js.map +1 -1
  47. package/package.json +6 -6
  48. package/src/component/FluxAction.vue +1 -1
  49. package/src/component/FluxActionBar.vue +2 -2
  50. package/src/component/FluxActionPane.vue +1 -1
  51. package/src/component/FluxAdaptiveGroup.vue +2 -2
  52. package/src/component/FluxAdaptiveSlot.vue +2 -2
  53. package/src/component/FluxAlert.vue +1 -1
  54. package/src/component/FluxAnimatedColors.vue +1 -1
  55. package/src/component/FluxAspectRatio.vue +1 -1
  56. package/src/component/FluxAvatar.vue +2 -2
  57. package/src/component/FluxBadge.vue +2 -2
  58. package/src/component/FluxBorderShine.vue +1 -1
  59. package/src/component/FluxBoxedIcon.vue +1 -1
  60. package/src/component/FluxButton.vue +2 -2
  61. package/src/component/FluxButtonGroup.vue +1 -1
  62. package/src/component/FluxButtonStack.vue +1 -1
  63. package/src/component/FluxCalendar.vue +588 -179
  64. package/src/component/FluxCalendarItem.vue +79 -0
  65. package/src/component/FluxCheckbox.vue +2 -2
  66. package/src/component/FluxChip.vue +2 -2
  67. package/src/component/FluxClickablePane.vue +2 -2
  68. package/src/component/FluxColorPicker.vue +2 -2
  69. package/src/component/FluxColorSelect.vue +3 -3
  70. package/src/component/FluxColumn.vue +1 -1
  71. package/src/component/FluxCommandPalette.vue +4 -4
  72. package/src/component/FluxCommandPaletteGroup.vue +1 -1
  73. package/src/component/FluxCommandPaletteItem.vue +1 -1
  74. package/src/component/FluxComment.vue +2 -2
  75. package/src/component/FluxConfirm.vue +1 -1
  76. package/src/component/FluxContainer.vue +1 -1
  77. package/src/component/FluxDataTable.vue +1 -2
  78. package/src/component/FluxDatePicker.vue +3 -3
  79. package/src/component/FluxDestructiveButton.vue +1 -1
  80. package/src/component/FluxDisabled.vue +1 -1
  81. package/src/component/FluxDivider.vue +2 -2
  82. package/src/component/FluxDotPattern.vue +1 -1
  83. package/src/component/FluxDropZone.vue +4 -4
  84. package/src/component/FluxExpandable.vue +3 -3
  85. package/src/component/FluxExpandableGroup.vue +2 -2
  86. package/src/component/FluxFader.vue +1 -1
  87. package/src/component/FluxFaderItem.vue +1 -1
  88. package/src/component/FluxFilter.vue +2 -2
  89. package/src/component/FluxFilterBar.vue +5 -6
  90. package/src/component/FluxFilterBase.vue +2 -2
  91. package/src/component/FluxFilterDate.vue +2 -2
  92. package/src/component/FluxFilterDateRange.vue +2 -2
  93. package/src/component/FluxFilterOption.vue +2 -2
  94. package/src/component/FluxFilterOptionAsync.vue +1 -1
  95. package/src/component/FluxFilterOptions.vue +2 -2
  96. package/src/component/FluxFilterOptionsAsync.vue +1 -1
  97. package/src/component/FluxFilterRange.vue +2 -2
  98. package/src/component/FluxFilterWindow.vue +3 -3
  99. package/src/component/FluxFlickeringGrid.vue +1 -1
  100. package/src/component/FluxFlyout.vue +2 -2
  101. package/src/component/FluxFocalPointEditor.vue +3 -3
  102. package/src/component/FluxFocalPointImage.vue +1 -1
  103. package/src/component/FluxForm.vue +1 -1
  104. package/src/component/FluxFormColumn.vue +1 -1
  105. package/src/component/FluxFormDateInput.vue +3 -3
  106. package/src/component/FluxFormDateRangeInput.vue +4 -4
  107. package/src/component/FluxFormDateTimeInput.vue +3 -3
  108. package/src/component/FluxFormField.vue +3 -3
  109. package/src/component/FluxFormFieldAddition.vue +1 -1
  110. package/src/component/FluxFormGrid.vue +1 -1
  111. package/src/component/FluxFormInput.vue +3 -3
  112. package/src/component/FluxFormInputAddition.vue +2 -2
  113. package/src/component/FluxFormInputGroup.vue +2 -2
  114. package/src/component/FluxFormPinInput.vue +3 -3
  115. package/src/component/FluxFormRangeSlider.vue +3 -3
  116. package/src/component/FluxFormRow.vue +1 -1
  117. package/src/component/FluxFormSection.vue +1 -1
  118. package/src/component/FluxFormSelect.vue +4 -4
  119. package/src/component/FluxFormSelectAsync.vue +6 -6
  120. package/src/component/FluxFormSlider.vue +2 -2
  121. package/src/component/FluxFormTextArea.vue +2 -2
  122. package/src/component/FluxFormTimeZonePicker.vue +4 -4
  123. package/src/component/FluxFormTreeViewSelect.vue +9 -12
  124. package/src/component/FluxGallery.vue +3 -3
  125. package/src/component/FluxGalleryItem.vue +1 -1
  126. package/src/component/FluxGrid.vue +1 -1
  127. package/src/component/FluxGridColumn.vue +1 -1
  128. package/src/component/FluxGridPattern.vue +1 -1
  129. package/src/component/FluxIcon.vue +2 -2
  130. package/src/component/FluxInfo.vue +2 -2
  131. package/src/component/FluxItem.vue +1 -1
  132. package/src/component/FluxItemActions.vue +1 -1
  133. package/src/component/FluxItemContent.vue +1 -1
  134. package/src/component/FluxItemMedia.vue +1 -1
  135. package/src/component/FluxItemStack.vue +1 -1
  136. package/src/component/FluxKanban.vue +78 -7
  137. package/src/component/FluxKanbanColumn.vue +225 -32
  138. package/src/component/FluxKanbanItem.vue +162 -0
  139. package/src/component/FluxLayerPane.vue +1 -1
  140. package/src/component/FluxLayerPaneSecondary.vue +1 -1
  141. package/src/component/FluxLegend.vue +1 -1
  142. package/src/component/FluxLink.vue +1 -1
  143. package/src/component/FluxMenu.vue +1 -1
  144. package/src/component/FluxMenuCollapsible.vue +3 -3
  145. package/src/component/FluxMenuGroup.vue +1 -1
  146. package/src/component/FluxMenuItem.vue +2 -2
  147. package/src/component/FluxMenuSubHeader.vue +1 -1
  148. package/src/component/FluxMenuTitle.vue +1 -1
  149. package/src/component/FluxNotice.vue +3 -3
  150. package/src/component/FluxOverflowBar.vue +1 -1
  151. package/src/component/FluxOverlay.vue +3 -3
  152. package/src/component/FluxOverlayProvider.vue +2 -2
  153. package/src/component/FluxPagination.vue +3 -3
  154. package/src/component/FluxPaginationBar.vue +2 -2
  155. package/src/component/FluxPaginationButton.vue +1 -1
  156. package/src/component/FluxPane.vue +1 -1
  157. package/src/component/FluxPaneBody.vue +1 -1
  158. package/src/component/FluxPaneFooter.vue +1 -1
  159. package/src/component/FluxPaneGroup.vue +1 -1
  160. package/src/component/FluxPaneHeader.vue +2 -2
  161. package/src/component/FluxPaneIllustration.vue +1 -1
  162. package/src/component/FluxPaneMedia.vue +1 -1
  163. package/src/component/FluxPercentageBar.vue +1 -1
  164. package/src/component/FluxPersona.vue +1 -1
  165. package/src/component/FluxPlaceholder.vue +1 -1
  166. package/src/component/FluxPressable.vue +1 -1
  167. package/src/component/FluxPrimaryButton.vue +1 -1
  168. package/src/component/FluxPrimaryLinkButton.vue +1 -1
  169. package/src/component/FluxProgressBar.vue +2 -2
  170. package/src/component/FluxPrompt.vue +1 -1
  171. package/src/component/FluxPublishButton.vue +1 -1
  172. package/src/component/FluxQuantitySelector.vue +2 -2
  173. package/src/component/FluxRemove.vue +2 -2
  174. package/src/component/FluxRoot.vue +2 -2
  175. package/src/component/FluxRow.vue +1 -1
  176. package/src/component/FluxSecondaryButton.vue +1 -1
  177. package/src/component/FluxSecondaryLinkButton.vue +1 -1
  178. package/src/component/FluxSegmentedControl.vue +1 -1
  179. package/src/component/FluxSeparator.vue +1 -1
  180. package/src/component/FluxSlideOver.vue +3 -3
  181. package/src/component/FluxSnackbar.vue +2 -2
  182. package/src/component/FluxSnackbarProvider.vue +2 -2
  183. package/src/component/FluxSpacer.vue +1 -1
  184. package/src/component/FluxSpinner.vue +1 -1
  185. package/src/component/FluxSplitButton.vue +2 -2
  186. package/src/component/FluxStack.vue +2 -2
  187. package/src/component/FluxStatistic.vue +2 -2
  188. package/src/component/FluxStepper.vue +1 -1
  189. package/src/component/FluxStepperStep.vue +1 -1
  190. package/src/component/FluxStepperSteps.vue +2 -2
  191. package/src/component/FluxTab.vue +2 -2
  192. package/src/component/FluxTabBar.vue +75 -7
  193. package/src/component/FluxTabBarItem.vue +35 -4
  194. package/src/component/FluxTable.vue +3 -4
  195. package/src/component/FluxTableActions.vue +1 -1
  196. package/src/component/FluxTableBar.vue +3 -3
  197. package/src/component/FluxTableCell.vue +3 -3
  198. package/src/component/FluxTableHeader.vue +3 -3
  199. package/src/component/FluxTableRow.vue +1 -1
  200. package/src/component/FluxTabs.vue +10 -4
  201. package/src/component/FluxTag.vue +2 -2
  202. package/src/component/FluxTicks.vue +1 -1
  203. package/src/component/FluxTimeline.vue +1 -1
  204. package/src/component/FluxTimelineItem.vue +2 -2
  205. package/src/component/FluxToggle.vue +2 -2
  206. package/src/component/FluxToolbar.vue +2 -2
  207. package/src/component/FluxTooltip.vue +1 -1
  208. package/src/component/FluxTooltipProvider.vue +3 -3
  209. package/src/component/FluxTreeView.vue +3 -4
  210. package/src/component/FluxWindow.vue +1 -1
  211. package/src/component/calendar/FluxCalendarItemDisplay.vue +117 -0
  212. package/src/component/calendar/FluxCalendarMonthView.vue +134 -0
  213. package/src/component/calendar/FluxCalendarTimeGridView.vue +550 -0
  214. package/src/component/calendar/index.ts +3 -0
  215. package/src/component/index.ts +2 -2
  216. package/src/component/primitive/CoordinatePicker.vue +2 -2
  217. package/src/component/primitive/CoordinatePickerThumb.vue +2 -2
  218. package/src/component/primitive/DialogLayout.vue +1 -1
  219. package/src/component/primitive/FilterBadge.vue +2 -2
  220. package/src/component/primitive/FilterItem.vue +1 -1
  221. package/src/component/primitive/FilterMenuRenderer.ts +2 -2
  222. package/src/component/primitive/FilterOptionBase.vue +6 -6
  223. package/src/component/primitive/SelectBase.vue +13 -13
  224. package/src/component/primitive/SliderBase.vue +3 -3
  225. package/src/component/primitive/SliderThumb.vue +2 -2
  226. package/src/component/primitive/SliderTrack.vue +1 -1
  227. package/src/component/primitive/TreeNodeRenderer.vue +3 -4
  228. package/src/component/primitive/VNodeRenderer.ts +1 -2
  229. package/src/composable/index.ts +3 -0
  230. package/src/composable/private/index.ts +5 -8
  231. package/src/composable/private/useAsyncFilterOptions.ts +9 -15
  232. package/src/composable/private/useCommandPalette.ts +2 -2
  233. package/src/composable/private/useDateFlyout.ts +1 -1
  234. package/src/composable/private/useDropdownPopup.ts +1 -1
  235. package/src/composable/private/useFilterOption.ts +2 -2
  236. package/src/composable/private/useFormSelect.ts +2 -3
  237. package/src/composable/private/useKanban.ts +528 -25
  238. package/src/composable/private/useKanbanAutoScroll.ts +95 -0
  239. package/src/composable/private/useTranslate.ts +1 -2
  240. package/src/composable/private/useTreeView.ts +1 -1
  241. package/src/composable/useAdaptiveGroupInjection.ts +1 -1
  242. package/src/composable/useBreakpoints.ts +1 -2
  243. package/src/composable/useCalendarInjection.ts +6 -0
  244. package/src/composable/useDisabled.ts +1 -2
  245. package/src/composable/useDisabledInjection.ts +1 -1
  246. package/src/composable/useExpandableGroupInjection.ts +1 -1
  247. package/src/composable/useFilterInjection.ts +1 -1
  248. package/src/composable/useFlyoutInjection.ts +1 -1
  249. package/src/composable/useFormFieldInjection.ts +1 -1
  250. package/src/composable/useKanbanInjection.ts +12 -0
  251. package/src/composable/useTabBarInjection.ts +10 -0
  252. package/src/composable/useTableInjection.ts +1 -1
  253. package/src/composable/useTooltipInjection.ts +1 -1
  254. package/src/css/component/Action.module.scss +1 -1
  255. package/src/css/component/AdaptiveSlot.module.scss +5 -7
  256. package/src/css/component/Avatar.module.scss +1 -1
  257. package/src/css/component/Badge.module.scss +1 -1
  258. package/src/css/component/Button.module.scss +1 -1
  259. package/src/css/component/Calendar.module.scss +274 -44
  260. package/src/css/component/Chip.module.scss +1 -1
  261. package/src/css/component/Color.module.scss +1 -1
  262. package/src/css/component/CommandPalette.module.scss +1 -1
  263. package/src/css/component/DatePicker.module.scss +1 -1
  264. package/src/css/component/Expandable.module.scss +1 -1
  265. package/src/css/component/Form.module.scss +1 -1
  266. package/src/css/component/Gallery.module.scss +1 -1
  267. package/src/css/component/Grid.module.scss +1 -1
  268. package/src/css/component/Item.module.scss +1 -1
  269. package/src/css/component/Kanban.module.scss +189 -0
  270. package/src/css/component/Layout.module.scss +1 -1
  271. package/src/css/component/Menu.module.scss +1 -1
  272. package/src/css/component/Notice.module.scss +1 -1
  273. package/src/css/component/Overlay.module.scss +4 -4
  274. package/src/css/component/Pagination.module.scss +1 -1
  275. package/src/css/component/Pane.module.scss +2 -1
  276. package/src/css/component/Placeholder.module.scss +1 -1
  277. package/src/css/component/Remove.module.scss +1 -1
  278. package/src/css/component/SegmentedControl.module.scss +1 -1
  279. package/src/css/component/Snackbar.module.scss +1 -1
  280. package/src/css/component/Tab.module.scss +138 -34
  281. package/src/css/component/Table.module.scss +1 -1
  282. package/src/css/component/TreeView.module.scss +1 -1
  283. package/src/css/component/TreeViewSelect.module.scss +1 -1
  284. package/src/css/component/base/Button.module.scss +1 -1
  285. package/src/css/component/primitive/Slider.module.scss +1 -1
  286. package/src/css/component/primitive/TreeNode.module.scss +1 -1
  287. package/src/css/variables.scss +2 -2
  288. package/src/data/di.ts +94 -8
  289. package/src/data/filter.ts +4 -4
  290. package/src/data/i18n.ts +4 -0
  291. package/src/data/store.ts +1 -2
  292. package/src/transition/FluxBreakthroughTransition.vue +1 -1
  293. package/src/transition/FluxFadeTransition.vue +1 -1
  294. package/src/transition/FluxOverlayTransition.vue +1 -1
  295. package/src/transition/FluxRouteTransition.vue +1 -1
  296. package/src/transition/FluxSlideOverTransition.vue +1 -1
  297. package/src/transition/FluxTooltipTransition.vue +1 -1
  298. package/src/transition/FluxVerticalWindowTransition.vue +1 -1
  299. package/src/transition/FluxWindowTransition.vue +1 -1
  300. package/src/util/createDialogRenderer.ts +3 -4
  301. package/src/util/createLabelForDateRange.ts +1 -1
  302. package/src/component/FluxCalendarEvent.vue +0 -42
  303. package/src/component/FluxKanbanCard.vue +0 -105
  304. package/src/css/component/FluxKanban.module.scss +0 -7
  305. package/src/css/component/FluxKanbanCard.module.scss +0 -35
  306. package/src/css/component/FluxKanbanColumn.module.scss +0 -49
@@ -0,0 +1,550 @@
1
+ <template>
2
+ <div
3
+ :class="$style.timeGrid"
4
+ :style="cssVars">
5
+ <FluxWindowTransition :is-back="isTransitioningToPast">
6
+ <div
7
+ :key="viewKey"
8
+ :class="$style.timeGridInner">
9
+ <div :class="$style.timeGridHeader">
10
+ <div :class="$style.timeGridHeaderGutter"/>
11
+ <div :class="$style.timeGridHeaderDays">
12
+ <template v-for="d of viewDates" :key="d.toISODate()">
13
+ <div :class="clsx($style.timeGridHeaderDay, isToday(d) && $style.isToday)">
14
+ {{ formatDayHeader(d) }}
15
+ </div>
16
+ </template>
17
+ </div>
18
+ </div>
19
+
20
+ <div :class="$style.timeGridAllDay">
21
+ <div :class="$style.timeGridAllDayLabel">
22
+ {{ translate('flux.allDay') }}
23
+ </div>
24
+ <div :class="$style.timeGridAllDayDays">
25
+ <template v-for="d of viewDates" :key="d.toISODate()">
26
+ <div
27
+ :class="clsx(
28
+ $style.timeGridAllDayCell,
29
+ draggable && dropTargetAllDay === d.toSQLDate() && $style.isDropTarget
30
+ )"
31
+ @dragover="draggable ? onAllDayDragOver(d, $event) : undefined"
32
+ @dragleave="draggable ? onAllDayDragLeave(d) : undefined"
33
+ @drop="draggable ? onAllDayDrop(d, $event) : undefined">
34
+ <FluxCalendarItemDisplay
35
+ v-for="item of getAllDayItems(d)"
36
+ :key="item.id"
37
+ :data="item"/>
38
+ </div>
39
+ </template>
40
+ </div>
41
+ </div>
42
+
43
+ <div :class="$style.timeGridBody">
44
+ <div :class="$style.timeGridHours">
45
+ <template v-for="hour of hours" :key="hour">
46
+ <div
47
+ :class="$style.timeGridHourLabel"
48
+ :style="{height: `${pixelsPerMinute * 60}px`}">
49
+ <span :class="$style.timeGridHourLabelText">{{ formatHour(hour) }}</span>
50
+ </div>
51
+ </template>
52
+ </div>
53
+
54
+ <div :class="$style.timeGridDays">
55
+ <template v-for="d of viewDates" :key="d.toISODate()">
56
+ <div
57
+ :class="clsx(
58
+ $style.timeGridDay,
59
+ draggable && dropTargetDay === d.toSQLDate() && $style.isDropTarget
60
+ )"
61
+ :style="{height: `${totalHeight}px`}"
62
+ @dragover="draggable ? onColumnDragOver(d, $event) : undefined"
63
+ @dragleave="draggable ? onColumnDragLeave(d) : undefined"
64
+ @drop="draggable ? onColumnDrop(d, $event) : undefined">
65
+ <template v-for="positioned of getTimedItems(d)" :key="positioned.id">
66
+ <div
67
+ :class="clsx(
68
+ $style.timeGridDayItem,
69
+ positioned.clippedTop && $style.isClippedTop,
70
+ positioned.clippedBottom && $style.isClippedBottom,
71
+ resizeState && resizeState.id === positioned.id && $style.isResizing
72
+ )"
73
+ :style="{
74
+ top: `${positioned.top}px`,
75
+ height: `${positioned.height}px`,
76
+ left: `${positioned.left}%`,
77
+ width: `${positioned.width}%`
78
+ }">
79
+ <div :class="$style.timeGridDayItemBody">
80
+ <FluxCalendarItemDisplay :data="positioned.data"/>
81
+
82
+ <template v-if="draggable && !hasActiveDrag">
83
+ <div
84
+ :class="clsx($style.timeGridDayItemHandle, $style.isTop)"
85
+ @mousedown="(evt) => onResizeStart(positioned, 'top', evt)"/>
86
+ <div
87
+ :class="clsx($style.timeGridDayItemHandle, $style.isBottom)"
88
+ @mousedown="(evt) => onResizeStart(positioned, 'bottom', evt)"/>
89
+ </template>
90
+ </div>
91
+ </div>
92
+ </template>
93
+
94
+ <div
95
+ v-if="dropTargetDay === d.toSQLDate() && dropTargetMinutes !== null"
96
+ :class="$style.timeGridDropIndicator"
97
+ :style="{top: `${(dropTargetMinutes - hourRange[0] * 60) * pixelsPerMinute}px`}"/>
98
+ </div>
99
+ </template>
100
+ </div>
101
+ </div>
102
+ </div>
103
+ </FluxWindowTransition>
104
+ </div>
105
+ </template>
106
+
107
+ <script
108
+ lang="ts"
109
+ setup>
110
+ import { clsx } from 'clsx';
111
+ import { DateTime } from 'luxon';
112
+ import { computed, onBeforeUnmount, ref, unref } from 'vue';
113
+ import { useTranslate } from '~flux/components/composable/private';
114
+ import type { FluxCalendarItemData } from '~flux/components/data';
115
+ import { FluxWindowTransition } from '~flux/components/transition';
116
+ import FluxCalendarItemDisplay from './FluxCalendarItemDisplay.vue';
117
+ import $style from '~flux/components/css/component/Calendar.module.scss';
118
+
119
+ type Positioned = {
120
+ readonly id: string | number;
121
+ readonly data: FluxCalendarItemData;
122
+ readonly date: DateTime;
123
+ readonly duration: number;
124
+ readonly top: number;
125
+ readonly height: number;
126
+ readonly left: number;
127
+ readonly width: number;
128
+ readonly clippedTop: boolean;
129
+ readonly clippedBottom: boolean;
130
+ };
131
+
132
+ type ResizeState = {
133
+ readonly id: string | number;
134
+ readonly edge: 'top' | 'bottom';
135
+ readonly originalDate: DateTime;
136
+ readonly originalDuration: number;
137
+ readonly startY: number;
138
+ };
139
+
140
+ const emit = defineEmits<{
141
+ timeGridDrop: [DateTime];
142
+ allDayDrop: [DateTime];
143
+ resize: [{ id: string | number; fromDate: DateTime; toDate: DateTime; fromDuration: number; toDuration: number }];
144
+ }>();
145
+
146
+ const {
147
+ viewDates,
148
+ draggable,
149
+ items,
150
+ hasActiveDrag,
151
+ hourRange,
152
+ pixelsPerMinute,
153
+ snapMinutes,
154
+ dayCount
155
+ } = defineProps<{
156
+ readonly viewDates: DateTime[];
157
+ readonly isTransitioningToPast: boolean;
158
+ readonly draggable: boolean;
159
+ readonly items: FluxCalendarItemData[];
160
+ readonly hasActiveDrag: boolean;
161
+ readonly hourRange: readonly [number, number];
162
+ readonly pixelsPerMinute: number;
163
+ readonly snapMinutes: number;
164
+ readonly dayCount: 1 | 2 | 7;
165
+ }>();
166
+
167
+ const translate = useTranslate();
168
+ const dropTargetDay = ref<string | null>(null);
169
+ const dropTargetMinutes = ref<number | null>(null);
170
+ const dropTargetAllDay = ref<string | null>(null);
171
+
172
+ const resizeState = ref<ResizeState | null>(null);
173
+ const resizePreview = ref<{ id: string | number; date: DateTime; duration: number } | null>(null);
174
+
175
+ const hours = computed<number[]>(() => {
176
+ const [from, to] = hourRange;
177
+ const out: number[] = [];
178
+
179
+ for (let h = from; h < to; ++h) {
180
+ out.push(h);
181
+ }
182
+
183
+ return out;
184
+ });
185
+
186
+ const totalHeight = computed<number>(() =>
187
+ (hourRange[1] - hourRange[0]) * 60 * pixelsPerMinute
188
+ );
189
+
190
+ const cssVars = computed(() => ({
191
+ '--hour-height': `${pixelsPerMinute * 60}px`
192
+ } as Record<string, string>));
193
+
194
+ const viewKey = computed<string>(() => `${dayCount}-${viewDates[0].toISODate() ?? ''}`);
195
+
196
+ function isToday(d: DateTime): boolean {
197
+ return d.hasSame(DateTime.now(), 'day');
198
+ }
199
+
200
+ function formatDayHeader(d: DateTime): string {
201
+ if (dayCount === 1) {
202
+ return d.toLocaleString({weekday: 'long', day: 'numeric', month: 'long'});
203
+ }
204
+
205
+ if (dayCount === 2) {
206
+ return d.toLocaleString({weekday: 'long', day: 'numeric', month: 'short'});
207
+ }
208
+
209
+ return d.toLocaleString({weekday: 'short', day: 'numeric'});
210
+ }
211
+
212
+ function formatHour(hour: number): string {
213
+ return DateTime.fromObject({hour}).toFormat('HH:mm');
214
+ }
215
+
216
+ function getAllDayItems(d: DateTime): FluxCalendarItemData[] {
217
+ const dStr = d.toSQLDate();
218
+
219
+ return items.filter(item => item.allDay && item.date.toSQLDate() === dStr);
220
+ }
221
+
222
+ function getTimedItems(d: DateTime): Positioned[] {
223
+ const dStr = d.toSQLDate();
224
+ const matching = items
225
+ .map(item => {
226
+ if (item.allDay) {
227
+ return null;
228
+ }
229
+
230
+ const preview = unref(resizePreview);
231
+ const effectiveDate = preview && preview.id === item.id ? preview.date : item.date;
232
+ const effectiveDuration = preview && preview.id === item.id ? preview.duration : (item.duration ?? 60);
233
+
234
+ if (effectiveDate.toSQLDate() !== dStr) {
235
+ return null;
236
+ }
237
+
238
+ return {
239
+ id: item.id,
240
+ data: item,
241
+ date: effectiveDate,
242
+ duration: effectiveDuration
243
+ };
244
+ })
245
+ .filter((entry): entry is { id: string | number; data: FluxCalendarItemData; date: DateTime; duration: number } => entry !== null)
246
+ .sort((a, b) => a.date.toMillis() - b.date.toMillis());
247
+
248
+ const lanes = assignLanes(matching);
249
+
250
+ const [fromH, toH] = hourRange;
251
+ const viewportStartMin = fromH * 60;
252
+ const viewportEndMin = toH * 60;
253
+
254
+ const out: Positioned[] = [];
255
+
256
+ matching.forEach((m, idx) => {
257
+ const start = m.date.hour * 60 + m.date.minute;
258
+ const end = start + m.duration;
259
+
260
+ if (end <= viewportStartMin || start >= viewportEndMin) {
261
+ return;
262
+ }
263
+
264
+ const clampedStart = Math.max(start, viewportStartMin);
265
+ const clampedEnd = Math.min(end, viewportEndMin);
266
+ const top = (clampedStart - viewportStartMin) * pixelsPerMinute;
267
+ const height = Math.max(2, (clampedEnd - clampedStart) * pixelsPerMinute);
268
+
269
+ const {lane, totalLanes} = lanes[idx];
270
+ const width = 100 / totalLanes;
271
+ const left = lane * width;
272
+
273
+ out.push({
274
+ id: m.id,
275
+ data: m.data,
276
+ date: m.date,
277
+ duration: m.duration,
278
+ top,
279
+ height,
280
+ left,
281
+ width,
282
+ clippedTop: start < viewportStartMin,
283
+ clippedBottom: end > viewportEndMin
284
+ });
285
+ });
286
+
287
+ return out;
288
+ }
289
+
290
+ function assignLanes(matching: ReadonlyArray<{ readonly date: DateTime; readonly duration: number }>): { lane: number; totalLanes: number }[] {
291
+ const intervals = matching.map(m => {
292
+ const start = m.date.hour * 60 + m.date.minute;
293
+ return {start, end: start + m.duration};
294
+ });
295
+
296
+ const clusters: number[] = [];
297
+ let currentCluster = -1;
298
+ let currentClusterEnd = -Infinity;
299
+
300
+ for (let i = 0; i < intervals.length; ++i) {
301
+ if (intervals[i].start >= currentClusterEnd) {
302
+ ++currentCluster;
303
+ currentClusterEnd = intervals[i].end;
304
+ } else {
305
+ currentClusterEnd = Math.max(currentClusterEnd, intervals[i].end);
306
+ }
307
+
308
+ clusters[i] = currentCluster;
309
+ }
310
+
311
+ const lanes: number[] = [];
312
+ const clusterLaneEnds = new Map<number, number[]>();
313
+
314
+ for (let i = 0; i < intervals.length; ++i) {
315
+ const cid = clusters[i];
316
+
317
+ if (!clusterLaneEnds.has(cid)) {
318
+ clusterLaneEnds.set(cid, []);
319
+ }
320
+
321
+ const ends = clusterLaneEnds.get(cid)!;
322
+ let assigned = -1;
323
+
324
+ for (let li = 0; li < ends.length; ++li) {
325
+ if (ends[li] <= intervals[i].start) {
326
+ assigned = li;
327
+ break;
328
+ }
329
+ }
330
+
331
+ if (assigned === -1) {
332
+ ends.push(intervals[i].end);
333
+ assigned = ends.length - 1;
334
+ } else {
335
+ ends[assigned] = intervals[i].end;
336
+ }
337
+
338
+ lanes[i] = assigned;
339
+ }
340
+
341
+ const clusterTotal = new Map<number, number>();
342
+
343
+ for (const [cid, ends] of clusterLaneEnds) {
344
+ clusterTotal.set(cid, ends.length);
345
+ }
346
+
347
+ return intervals.map((_, i) => ({
348
+ lane: lanes[i],
349
+ totalLanes: clusterTotal.get(clusters[i])!
350
+ }));
351
+ }
352
+
353
+ function snapToMinutes(minutes: number): number {
354
+ return Math.round(minutes / snapMinutes) * snapMinutes;
355
+ }
356
+
357
+ let cachedDropTarget: HTMLElement | null = null;
358
+ let cachedDropRect: DOMRect | null = null;
359
+
360
+ function getDropTargetRect(target: HTMLElement): DOMRect {
361
+ if (cachedDropTarget !== target || !cachedDropRect) {
362
+ cachedDropTarget = target;
363
+ cachedDropRect = target.getBoundingClientRect();
364
+ }
365
+
366
+ return cachedDropRect;
367
+ }
368
+
369
+ function clearDropTargetCache(): void {
370
+ cachedDropTarget = null;
371
+ cachedDropRect = null;
372
+ }
373
+
374
+ function calculateDropMinutes(evt: DragEvent): number | null {
375
+ const target = evt.currentTarget as HTMLElement | null;
376
+
377
+ if (!target) {
378
+ return null;
379
+ }
380
+
381
+ const rect = getDropTargetRect(target);
382
+ const offsetY = evt.clientY - rect.top;
383
+ const minuteFromTop = offsetY / pixelsPerMinute;
384
+ const absoluteMinute = hourRange[0] * 60 + minuteFromTop;
385
+ const snapped = snapToMinutes(absoluteMinute);
386
+
387
+ return Math.max(hourRange[0] * 60, Math.min(hourRange[1] * 60 - snapMinutes, snapped));
388
+ }
389
+
390
+ function onColumnDragOver(d: DateTime, evt: DragEvent): void {
391
+ if (!hasActiveDrag) {
392
+ return;
393
+ }
394
+
395
+ evt.preventDefault();
396
+
397
+ if (evt.dataTransfer) {
398
+ evt.dataTransfer.dropEffect = 'move';
399
+ }
400
+
401
+ dropTargetDay.value = d.toSQLDate();
402
+ dropTargetMinutes.value = calculateDropMinutes(evt);
403
+ dropTargetAllDay.value = null;
404
+ }
405
+
406
+ function onColumnDragLeave(d: DateTime): void {
407
+ if (unref(dropTargetDay) === d.toSQLDate()) {
408
+ dropTargetDay.value = null;
409
+ dropTargetMinutes.value = null;
410
+ clearDropTargetCache();
411
+ }
412
+ }
413
+
414
+ function onColumnDrop(d: DateTime, evt: DragEvent): void {
415
+ evt.preventDefault();
416
+
417
+ const minutes = calculateDropMinutes(evt) ?? hourRange[0] * 60;
418
+ const toDate = d.startOf('day').plus({minutes});
419
+ emit('timeGridDrop', toDate);
420
+ dropTargetDay.value = null;
421
+ dropTargetMinutes.value = null;
422
+ clearDropTargetCache();
423
+ }
424
+
425
+ function onAllDayDragOver(d: DateTime, evt: DragEvent): void {
426
+ if (!hasActiveDrag) {
427
+ return;
428
+ }
429
+
430
+ evt.preventDefault();
431
+
432
+ if (evt.dataTransfer) {
433
+ evt.dataTransfer.dropEffect = 'move';
434
+ }
435
+
436
+ dropTargetAllDay.value = d.toSQLDate();
437
+ dropTargetDay.value = null;
438
+ dropTargetMinutes.value = null;
439
+ }
440
+
441
+ function onAllDayDragLeave(d: DateTime): void {
442
+ if (unref(dropTargetAllDay) === d.toSQLDate()) {
443
+ dropTargetAllDay.value = null;
444
+ }
445
+ }
446
+
447
+ function onAllDayDrop(d: DateTime, evt: DragEvent): void {
448
+ evt.preventDefault();
449
+ emit('allDayDrop', d.startOf('day'));
450
+ dropTargetAllDay.value = null;
451
+ }
452
+
453
+ function onResizeStart(positioned: Positioned, edge: 'top' | 'bottom', evt: MouseEvent): void {
454
+ if (positioned.id == null) {
455
+ return;
456
+ }
457
+
458
+ evt.preventDefault();
459
+ evt.stopPropagation();
460
+
461
+ resizeState.value = {
462
+ id: positioned.id,
463
+ edge,
464
+ originalDate: positioned.date,
465
+ originalDuration: positioned.duration,
466
+ startY: evt.clientY
467
+ };
468
+ resizePreview.value = {
469
+ id: positioned.id,
470
+ date: positioned.date,
471
+ duration: positioned.duration
472
+ };
473
+
474
+ document.addEventListener('mousemove', onResizeMove);
475
+ document.addEventListener('mouseup', onResizeEnd);
476
+ }
477
+
478
+ function onResizeMove(evt: MouseEvent): void {
479
+ const state = unref(resizeState);
480
+
481
+ if (!state) {
482
+ return;
483
+ }
484
+
485
+ const deltaY = evt.clientY - state.startY;
486
+ const deltaMinutes = deltaY / pixelsPerMinute;
487
+ const snappedDelta = snapToMinutes(deltaMinutes);
488
+
489
+ const minDuration = snapMinutes;
490
+ const rangeStartMin = hourRange[0] * 60;
491
+ const rangeEndMin = hourRange[1] * 60;
492
+
493
+ if (state.edge === 'bottom') {
494
+ const newDuration = Math.max(minDuration, state.originalDuration + snappedDelta);
495
+ const startMin = state.originalDate.hour * 60 + state.originalDate.minute;
496
+ const clampedDuration = Math.min(newDuration, rangeEndMin - startMin);
497
+ resizePreview.value = {
498
+ id: state.id,
499
+ date: state.originalDate,
500
+ duration: clampedDuration
501
+ };
502
+ } else {
503
+ // top edge: move start backwards (negative delta = earlier start)
504
+ const originalStartMin = state.originalDate.hour * 60 + state.originalDate.minute;
505
+ const originalEndMin = originalStartMin + state.originalDuration;
506
+ let newStartMin = originalStartMin + snappedDelta;
507
+ newStartMin = Math.max(rangeStartMin, Math.min(originalEndMin - minDuration, newStartMin));
508
+ const newDuration = originalEndMin - newStartMin;
509
+ const newDate = state.originalDate.startOf('day').plus({minutes: newStartMin});
510
+ resizePreview.value = {
511
+ id: state.id,
512
+ date: newDate,
513
+ duration: newDuration
514
+ };
515
+ }
516
+ }
517
+
518
+ function onResizeEnd(): void {
519
+ document.removeEventListener('mousemove', onResizeMove);
520
+ document.removeEventListener('mouseup', onResizeEnd);
521
+
522
+ const state = unref(resizeState);
523
+ const preview = unref(resizePreview);
524
+
525
+ resizeState.value = null;
526
+ resizePreview.value = null;
527
+
528
+ if (!state || !preview) {
529
+ return;
530
+ }
531
+
532
+ if (preview.date.toMillis() === state.originalDate.toMillis()
533
+ && preview.duration === state.originalDuration) {
534
+ return;
535
+ }
536
+
537
+ emit('resize', {
538
+ id: state.id,
539
+ fromDate: state.originalDate,
540
+ toDate: preview.date,
541
+ fromDuration: state.originalDuration,
542
+ toDuration: preview.duration
543
+ });
544
+ }
545
+
546
+ onBeforeUnmount(() => {
547
+ document.removeEventListener('mousemove', onResizeMove);
548
+ document.removeEventListener('mouseup', onResizeEnd);
549
+ });
550
+ </script>
@@ -0,0 +1,3 @@
1
+ export { default as FluxCalendarItemDisplay } from './FluxCalendarItemDisplay.vue';
2
+ export { default as FluxCalendarMonthView } from './FluxCalendarMonthView.vue';
3
+ export { default as FluxCalendarTimeGridView } from './FluxCalendarTimeGridView.vue';
@@ -15,7 +15,7 @@ export { default as FluxButton } from './FluxButton.vue';
15
15
  export { default as FluxButtonGroup } from './FluxButtonGroup.vue';
16
16
  export { default as FluxButtonStack } from './FluxButtonStack.vue';
17
17
  export { default as FluxCalendar } from './FluxCalendar.vue';
18
- export { default as FluxCalendarEvent } from './FluxCalendarEvent.vue';
18
+ export { default as FluxCalendarItem } from './FluxCalendarItem.vue';
19
19
  export { default as FluxCheckbox } from './FluxCheckbox.vue';
20
20
  export { default as FluxChip } from './FluxChip.vue';
21
21
  export { default as FluxClickablePane } from './FluxClickablePane.vue';
@@ -81,8 +81,8 @@ export { default as FluxGridPattern } from './FluxGridPattern.vue';
81
81
  export { default as FluxIcon } from './FluxIcon.vue';
82
82
  export { default as FluxInfo } from './FluxInfo.vue';
83
83
  export { default as FluxKanban } from './FluxKanban.vue';
84
- export { default as FluxKanbanCard } from './FluxKanbanCard.vue';
85
84
  export { default as FluxKanbanColumn } from './FluxKanbanColumn.vue';
85
+ export { default as FluxKanbanItem } from './FluxKanbanItem.vue';
86
86
  export { default as FluxInfoStack } from './FluxInfoStack.vue';
87
87
  export { default as FluxItem } from './FluxItem.vue';
88
88
  export { default as FluxItemActions } from './FluxItemActions.vue';
@@ -20,9 +20,9 @@
20
20
  import { roundStep } from '@basmilius/utils';
21
21
  import { unrefTemplateElement } from '@flux-ui/internals';
22
22
  import { computed, onUnmounted, ref, toRef, unref, useTemplateRef, watch } from 'vue';
23
- import { useDisabled } from '$flux/composable';
23
+ import { useDisabled } from '~flux/components/composable';
24
24
  import CoordinatePickerThumb from './CoordinatePickerThumb.vue';
25
- import $style from '$flux/css/component/primitive/CoordinatePicker.module.scss';
25
+ import $style from '~flux/components/css/component/primitive/CoordinatePicker.module.scss';
26
26
 
27
27
  const emit = defineEmits<{
28
28
  dragging: [boolean];
@@ -23,8 +23,8 @@
23
23
  setup>
24
24
  import { clsx } from 'clsx';
25
25
  import { toRef, unref } from 'vue';
26
- import { useDisabled } from '$flux/composable';
27
- import $style from '$flux/css/component/primitive/CoordinatePicker.module.scss';
26
+ import { useDisabled } from '~flux/components/composable';
27
+ import $style from '~flux/components/css/component/primitive/CoordinatePicker.module.scss';
28
28
 
29
29
  const emit = defineEmits<{
30
30
  decrement: [boolean, boolean];
@@ -23,8 +23,8 @@
23
23
  <script
24
24
  lang="ts"
25
25
  setup>
26
- import type { VNode } from 'vue';
27
26
  import type { FluxIconName } from '@flux-ui/types';
27
+ import type { VNode } from 'vue';
28
28
  import FluxPane from '../FluxPane.vue';
29
29
  import FluxPaneBody from '../FluxPaneBody.vue';
30
30
  import FluxPaneFooter from '../FluxPaneFooter.vue';
@@ -13,8 +13,8 @@
13
13
  import { useLoaded } from '@basmilius/common';
14
14
  import type { FluxFilterItem, FluxFilterValue } from '@flux-ui/types';
15
15
  import { computed, ref, unref, watch } from 'vue';
16
- import { FluxBadge } from '$flux/component';
17
- import $style from '$flux/css/component/Filter.module.scss';
16
+ import FluxBadge from '../FluxBadge.vue';
17
+ import $style from '~flux/components/css/component/Filter.module.scss';
18
18
 
19
19
  const emit = defineEmits<{
20
20
  click: [MouseEvent];
@@ -15,7 +15,7 @@
15
15
  import { useLoaded } from '@basmilius/common';
16
16
  import type { FluxFilterItem, FluxFilterValue } from '@flux-ui/types';
17
17
  import { computed, ref, unref, watch } from 'vue';
18
- import FluxMenuItem from '$flux/component/FluxMenuItem.vue';
18
+ import FluxMenuItem from '../FluxMenuItem.vue';
19
19
 
20
20
  const emit = defineEmits<{
21
21
  click: [MouseEvent];
@@ -1,6 +1,6 @@
1
1
  import type { FluxFilterItem, FluxFilterValue } from '@flux-ui/types';
2
- import { defineComponent, h, isVNode, unref, type VNode } from 'vue';
3
- import { useFilterInjection } from '$flux/composable';
2
+ import { defineComponent, h, isVNode, type VNode, unref } from 'vue';
3
+ import { useFilterInjection } from '~flux/components/composable';
4
4
  import FluxMenuGroup from '../FluxMenuGroup.vue';
5
5
  import FluxSeparator from '../FluxSeparator.vue';
6
6
  import FilterItem from './FilterItem.vue';
@@ -38,12 +38,12 @@
38
38
  lang="ts"
39
39
  setup>
40
40
  import type { FluxFilterOptionItem, FluxFilterOptionRow, FluxFilterValueSingle } from '@flux-ui/types';
41
- import { isFluxFilterOptionHeader, isFluxFilterOptionItem } from '$flux/data';
42
- import FluxMenuItem from '$flux/component/FluxMenuItem.vue';
43
- import FluxFormInput from '$flux/component/FluxFormInput.vue';
44
- import FluxMenuGroup from '$flux/component/FluxMenuGroup.vue';
45
- import FluxMenuSubHeader from '$flux/component/FluxMenuSubHeader.vue';
46
- import $style from '$flux/css/component/Filter.module.scss';
41
+ import { isFluxFilterOptionHeader, isFluxFilterOptionItem } from '~flux/components/data';
42
+ import FluxFormInput from '../FluxFormInput.vue';
43
+ import FluxMenuGroup from '../FluxMenuGroup.vue';
44
+ import FluxMenuItem from '../FluxMenuItem.vue';
45
+ import FluxMenuSubHeader from '../FluxMenuSubHeader.vue';
46
+ import $style from '~flux/components/css/component/Filter.module.scss';
47
47
 
48
48
  const emit = defineEmits<{
49
49
  select: [FluxFilterValueSingle];