@flux-ui/components 3.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/README.md +45 -0
  2. package/package.json +77 -0
  3. package/src/component/FluxAction.vue +27 -0
  4. package/src/component/FluxActionBar.vue +94 -0
  5. package/src/component/FluxActionPane.vue +40 -0
  6. package/src/component/FluxActions.vue +27 -0
  7. package/src/component/FluxAlert.vue +37 -0
  8. package/src/component/FluxAnimatedColors.vue +141 -0
  9. package/src/component/FluxAspectRatio.vue +21 -0
  10. package/src/component/FluxAutoGrid.vue +27 -0
  11. package/src/component/FluxAvatar.vue +119 -0
  12. package/src/component/FluxBadge.vue +84 -0
  13. package/src/component/FluxBadgeStack.vue +18 -0
  14. package/src/component/FluxBorderShine.vue +36 -0
  15. package/src/component/FluxBoxedIcon.vue +36 -0
  16. package/src/component/FluxButton.vue +110 -0
  17. package/src/component/FluxButtonGroup.vue +15 -0
  18. package/src/component/FluxButtonStack.vue +28 -0
  19. package/src/component/FluxCalendar.vue +254 -0
  20. package/src/component/FluxCalendarEvent.vue +41 -0
  21. package/src/component/FluxCheckbox.vue +60 -0
  22. package/src/component/FluxChip.vue +57 -0
  23. package/src/component/FluxClickablePane.vue +61 -0
  24. package/src/component/FluxColorPicker.vue +265 -0
  25. package/src/component/FluxColorSelect.vue +81 -0
  26. package/src/component/FluxComment.vue +71 -0
  27. package/src/component/FluxConfirm.vue +42 -0
  28. package/src/component/FluxContainer.vue +23 -0
  29. package/src/component/FluxDataTable.vue +96 -0
  30. package/src/component/FluxDatePicker.vue +353 -0
  31. package/src/component/FluxDestructiveButton.vue +28 -0
  32. package/src/component/FluxDisabled.vue +22 -0
  33. package/src/component/FluxDivider.vue +37 -0
  34. package/src/component/FluxDotPattern.vue +72 -0
  35. package/src/component/FluxDropZone.vue +202 -0
  36. package/src/component/FluxDynamicView.vue +16 -0
  37. package/src/component/FluxExpandable.vue +119 -0
  38. package/src/component/FluxExpandableGroup.vue +53 -0
  39. package/src/component/FluxFader.vue +64 -0
  40. package/src/component/FluxFaderItem.vue +15 -0
  41. package/src/component/FluxFilter.vue +133 -0
  42. package/src/component/FluxFilterDate.vue +58 -0
  43. package/src/component/FluxFilterDateRange.vue +59 -0
  44. package/src/component/FluxFilterOption.vue +49 -0
  45. package/src/component/FluxFilterOptionAsync.vue +103 -0
  46. package/src/component/FluxFilterOptions.vue +62 -0
  47. package/src/component/FluxFilterOptionsAsync.vue +113 -0
  48. package/src/component/FluxFilterRange.vue +91 -0
  49. package/src/component/FluxFlickeringGrid.vue +141 -0
  50. package/src/component/FluxFlyout.vue +205 -0
  51. package/src/component/FluxFocalPointEditor.vue +137 -0
  52. package/src/component/FluxFocalPointImage.vue +29 -0
  53. package/src/component/FluxForm.vue +35 -0
  54. package/src/component/FluxFormColumn.vue +15 -0
  55. package/src/component/FluxFormDateInput.vue +92 -0
  56. package/src/component/FluxFormDateRangeInput.vue +87 -0
  57. package/src/component/FluxFormDateTimeInput.vue +120 -0
  58. package/src/component/FluxFormField.vue +98 -0
  59. package/src/component/FluxFormFieldAddition.vue +37 -0
  60. package/src/component/FluxFormInput.vue +223 -0
  61. package/src/component/FluxFormInputAddition.vue +31 -0
  62. package/src/component/FluxFormInputGroup.vue +25 -0
  63. package/src/component/FluxFormPinInput.vue +135 -0
  64. package/src/component/FluxFormRangeSlider.vue +179 -0
  65. package/src/component/FluxFormRow.vue +15 -0
  66. package/src/component/FluxFormSection.vue +23 -0
  67. package/src/component/FluxFormSelect.vue +59 -0
  68. package/src/component/FluxFormSelectAsync.vue +118 -0
  69. package/src/component/FluxFormSlider.vue +123 -0
  70. package/src/component/FluxFormTextArea.vue +53 -0
  71. package/src/component/FluxFormTimeZonePicker.vue +713 -0
  72. package/src/component/FluxGallery.vue +99 -0
  73. package/src/component/FluxGalleryItem.vue +49 -0
  74. package/src/component/FluxGrid.vue +28 -0
  75. package/src/component/FluxGridColumn.vue +31 -0
  76. package/src/component/FluxGridPattern.vue +60 -0
  77. package/src/component/FluxIcon.vue +79 -0
  78. package/src/component/FluxInfo.vue +28 -0
  79. package/src/component/FluxInfoStack.vue +17 -0
  80. package/src/component/FluxLegend.vue +27 -0
  81. package/src/component/FluxLink.vue +35 -0
  82. package/src/component/FluxMenu.vue +31 -0
  83. package/src/component/FluxMenuGroup.vue +21 -0
  84. package/src/component/FluxMenuItem.vue +84 -0
  85. package/src/component/FluxMenuOptions.vue +38 -0
  86. package/src/component/FluxMenuSubHeader.vue +33 -0
  87. package/src/component/FluxMenuTitle.vue +17 -0
  88. package/src/component/FluxNotice.vue +79 -0
  89. package/src/component/FluxNoticeStack.vue +17 -0
  90. package/src/component/FluxOverlay.vue +31 -0
  91. package/src/component/FluxPagination.vue +148 -0
  92. package/src/component/FluxPaginationBar.vue +81 -0
  93. package/src/component/FluxPane.vue +45 -0
  94. package/src/component/FluxPaneBody.vue +15 -0
  95. package/src/component/FluxPaneDeck.vue +24 -0
  96. package/src/component/FluxPaneFooter.vue +15 -0
  97. package/src/component/FluxPaneGroup.vue +15 -0
  98. package/src/component/FluxPaneHeader.vue +44 -0
  99. package/src/component/FluxPaneIllustration.vue +68 -0
  100. package/src/component/FluxPaneMedia.vue +31 -0
  101. package/src/component/FluxPercentageBar.vue +45 -0
  102. package/src/component/FluxPersona.vue +48 -0
  103. package/src/component/FluxPlaceholder.vue +56 -0
  104. package/src/component/FluxPressable.vue +77 -0
  105. package/src/component/FluxPrimaryButton.vue +28 -0
  106. package/src/component/FluxProgressBar.vue +75 -0
  107. package/src/component/FluxPrompt.vue +77 -0
  108. package/src/component/FluxPublishButton.vue +59 -0
  109. package/src/component/FluxQuantitySelector.vue +109 -0
  110. package/src/component/FluxRemove.vue +34 -0
  111. package/src/component/FluxRoot.vue +60 -0
  112. package/src/component/FluxSecondaryButton.vue +28 -0
  113. package/src/component/FluxSegmentedControl.vue +77 -0
  114. package/src/component/FluxSegmentedView.vue +15 -0
  115. package/src/component/FluxSeparator.vue +19 -0
  116. package/src/component/FluxSlideOver.vue +25 -0
  117. package/src/component/FluxSnackbar.vue +154 -0
  118. package/src/component/FluxSnackbarProvider.vue +34 -0
  119. package/src/component/FluxSpacer.vue +9 -0
  120. package/src/component/FluxSpacing.vue +32 -0
  121. package/src/component/FluxSpinner.vue +48 -0
  122. package/src/component/FluxSplitButton.vue +61 -0
  123. package/src/component/FluxStack.vue +40 -0
  124. package/src/component/FluxStatistic.vue +68 -0
  125. package/src/component/FluxStepper.vue +69 -0
  126. package/src/component/FluxStepperStep.vue +15 -0
  127. package/src/component/FluxStepperSteps.vue +62 -0
  128. package/src/component/FluxTab.vue +23 -0
  129. package/src/component/FluxTabBar.vue +87 -0
  130. package/src/component/FluxTabBarItem.vue +104 -0
  131. package/src/component/FluxTable.vue +68 -0
  132. package/src/component/FluxTableActions.vue +16 -0
  133. package/src/component/FluxTableCell.vue +47 -0
  134. package/src/component/FluxTableHeader.vue +111 -0
  135. package/src/component/FluxTableRow.vue +15 -0
  136. package/src/component/FluxTabs.vue +91 -0
  137. package/src/component/FluxTag.vue +85 -0
  138. package/src/component/FluxTagStack.vue +18 -0
  139. package/src/component/FluxTicks.vue +44 -0
  140. package/src/component/FluxTimeline.vue +17 -0
  141. package/src/component/FluxTimelineItem.vue +73 -0
  142. package/src/component/FluxToggle.vue +64 -0
  143. package/src/component/FluxToolbar.vue +32 -0
  144. package/src/component/FluxToolbarGroup.vue +18 -0
  145. package/src/component/FluxTooltip.vue +56 -0
  146. package/src/component/FluxTooltipProvider.vue +176 -0
  147. package/src/component/FluxWindow.vue +47 -0
  148. package/src/component/index.ts +142 -0
  149. package/src/component/primitive/Anchor.vue +17 -0
  150. package/src/component/primitive/AnchorPopup.vue +194 -0
  151. package/src/component/primitive/CoordinatePicker.vue +155 -0
  152. package/src/component/primitive/CoordinatePickerThumb.vue +71 -0
  153. package/src/component/primitive/FilterItem.vue +44 -0
  154. package/src/component/primitive/FilterMenuRenderer.ts +233 -0
  155. package/src/component/primitive/FilterOptionBase.vue +67 -0
  156. package/src/component/primitive/SelectBase.vue +340 -0
  157. package/src/component/primitive/SliderBase.vue +89 -0
  158. package/src/component/primitive/SliderThumb.vue +64 -0
  159. package/src/component/primitive/SliderTrack.vue +22 -0
  160. package/src/component/primitive/VNodeRenderer.ts +11 -0
  161. package/src/component/primitive/index.ts +10 -0
  162. package/src/composable/index.ts +9 -0
  163. package/src/composable/private/index.ts +3 -0
  164. package/src/composable/private/useFormSelect.ts +66 -0
  165. package/src/composable/private/useLoaded.ts +21 -0
  166. package/src/composable/private/useTranslate.ts +35 -0
  167. package/src/composable/useBreakpoints.ts +54 -0
  168. package/src/composable/useDisabled.ts +9 -0
  169. package/src/composable/useDisabledInjection.ts +6 -0
  170. package/src/composable/useExpandableGroupInjection.ts +10 -0
  171. package/src/composable/useFilterInjection.ts +22 -0
  172. package/src/composable/useFlyoutInjection.ts +10 -0
  173. package/src/composable/useFormFieldInjection.ts +8 -0
  174. package/src/composable/useTableInjection.ts +11 -0
  175. package/src/css/base.scss +33 -0
  176. package/src/css/component/Action.module.scss +107 -0
  177. package/src/css/component/Avatar.module.scss +177 -0
  178. package/src/css/component/Badge.module.scss +189 -0
  179. package/src/css/component/Button.module.scss +293 -0
  180. package/src/css/component/Calendar.module.scss +171 -0
  181. package/src/css/component/Chip.module.scss +58 -0
  182. package/src/css/component/Color.module.scss +184 -0
  183. package/src/css/component/Comment.module.scss +123 -0
  184. package/src/css/component/DatePicker.module.scss +193 -0
  185. package/src/css/component/Divider.module.scss +79 -0
  186. package/src/css/component/DropZone.module.scss +99 -0
  187. package/src/css/component/Expandable.module.scss +112 -0
  188. package/src/css/component/Fader.module.scss +38 -0
  189. package/src/css/component/Filter.module.scss +80 -0
  190. package/src/css/component/Flyout.module.scss +63 -0
  191. package/src/css/component/FocalPoint.module.scss +84 -0
  192. package/src/css/component/Form.module.scss +812 -0
  193. package/src/css/component/Gallery.module.scss +64 -0
  194. package/src/css/component/Grid.module.scss +24 -0
  195. package/src/css/component/Icon.module.scss +104 -0
  196. package/src/css/component/Info.module.scss +15 -0
  197. package/src/css/component/Layout.module.scss +63 -0
  198. package/src/css/component/Legend.module.scss +32 -0
  199. package/src/css/component/Menu.module.scss +314 -0
  200. package/src/css/component/Notice.module.scss +279 -0
  201. package/src/css/component/Overlay.module.scss +149 -0
  202. package/src/css/component/Pagination.module.scss +59 -0
  203. package/src/css/component/Pane.module.scss +218 -0
  204. package/src/css/component/PercentageBar.module.scss +31 -0
  205. package/src/css/component/Placeholder.module.scss +72 -0
  206. package/src/css/component/Progress.module.scss +84 -0
  207. package/src/css/component/Remove.module.scss +29 -0
  208. package/src/css/component/Root.module.scss +8 -0
  209. package/src/css/component/SegmentedControl.module.scss +82 -0
  210. package/src/css/component/Snackbar.module.scss +227 -0
  211. package/src/css/component/Spinner.module.scss +36 -0
  212. package/src/css/component/Statistic.module.scss +118 -0
  213. package/src/css/component/Stepper.module.scss +103 -0
  214. package/src/css/component/Tab.module.scss +162 -0
  215. package/src/css/component/Table.module.scss +164 -0
  216. package/src/css/component/Timeline.module.scss +173 -0
  217. package/src/css/component/Toolbar.module.scss +82 -0
  218. package/src/css/component/Tooltip.module.scss +62 -0
  219. package/src/css/component/Transition.module.scss +142 -0
  220. package/src/css/component/Visual.module.scss +70 -0
  221. package/src/css/component/base/Button.module.scss +87 -0
  222. package/src/css/component/base/Effect.module.scss +139 -0
  223. package/src/css/component/base/Grid.module.scss +8 -0
  224. package/src/css/component/base/Pane.module.scss +54 -0
  225. package/src/css/component/primitive/CoordinatePicker.module.scss +24 -0
  226. package/src/css/component/primitive/Slider.module.scss +116 -0
  227. package/src/css/index.scss +5 -0
  228. package/src/css/layers.scss +1 -0
  229. package/src/css/mixin/breakpoints.scss +112 -0
  230. package/src/css/mixin/focus-ring.scss +56 -0
  231. package/src/css/mixin/hover.scss +7 -0
  232. package/src/css/mixin/index.scss +3 -0
  233. package/src/css/reset.scss +169 -0
  234. package/src/css/typography.scss +87 -0
  235. package/src/css/variables.scss +214 -0
  236. package/src/data/di.ts +42 -0
  237. package/src/data/filter.ts +9 -0
  238. package/src/data/helper.ts +9 -0
  239. package/src/data/i18n.ts +55 -0
  240. package/src/data/iconRegistry.ts +21 -0
  241. package/src/data/index.ts +8 -0
  242. package/src/data/inputMask.ts +34 -0
  243. package/src/data/store.ts +233 -0
  244. package/src/image/avatar-mask.svg +3 -0
  245. package/src/index.ts +25 -0
  246. package/src/transition/FluxAutoHeightTransition.vue +59 -0
  247. package/src/transition/FluxAutoWidthTransition.vue +59 -0
  248. package/src/transition/FluxBreakthroughTransition.vue +23 -0
  249. package/src/transition/FluxFadeTransition.vue +24 -0
  250. package/src/transition/FluxOverlayTransition.vue +22 -0
  251. package/src/transition/FluxRouteTransition.vue +23 -0
  252. package/src/transition/FluxSlideOverTransition.vue +22 -0
  253. package/src/transition/FluxTooltipTransition.vue +22 -0
  254. package/src/transition/FluxVerticalWindowTransition.vue +23 -0
  255. package/src/transition/FluxWindowTransition.vue +23 -0
  256. package/src/transition/index.ts +10 -0
  257. package/src/util/createDialogRenderer.ts +64 -0
  258. package/src/util/createLabelForDateRange.ts +61 -0
  259. package/src/util/index.ts +2 -0
  260. package/src/vite.d.ts +13 -0
  261. package/tsconfig.json +45 -0
@@ -0,0 +1,57 @@
1
+ <template>
2
+ <Component
3
+ :is="isSelectable ? 'button' : 'div'"
4
+ :class="clsx(
5
+ $style.chip,
6
+ isSelectable && $style.isSelectable,
7
+ isSelected && $style.isSelected
8
+ )"
9
+ @click="$emit('click', $event)">
10
+ <FluxFadeTransition v-if="isSelectable">
11
+ <FluxIcon
12
+ :key="selectableIcon"
13
+ :name="selectableIcon"
14
+ :size="16"/>
15
+ </FluxFadeTransition>
16
+
17
+ <FluxIcon
18
+ v-else-if="iconLeading"
19
+ :name="iconLeading"
20
+ :size="16"/>
21
+
22
+ <span>{{ label }}</span>
23
+
24
+ <FluxIcon
25
+ v-if="iconTrailing"
26
+ :name="iconTrailing"
27
+ :size="16"/>
28
+ </component>
29
+ </template>
30
+
31
+ <script
32
+ lang="ts"
33
+ setup>
34
+ import type { FluxIconName } from '@flux-ui/types';
35
+ import { clsx } from 'clsx';
36
+ import { computed } from 'vue';
37
+ import { FluxFadeTransition } from '$flux/transition';
38
+ import FluxIcon from './FluxIcon.vue';
39
+ import $style from '$flux/css/component/Chip.module.scss';
40
+
41
+ defineEmits<{
42
+ click: [MouseEvent];
43
+ }>();
44
+
45
+ const {
46
+ iconLeading,
47
+ isSelected
48
+ } = defineProps<{
49
+ readonly iconLeading?: FluxIconName;
50
+ readonly iconTrailing?: FluxIconName;
51
+ readonly isSelectable?: boolean;
52
+ readonly isSelected?: boolean;
53
+ readonly label: string;
54
+ }>();
55
+
56
+ const selectableIcon = computed<FluxIconName>(() => isSelected ? 'check' : (iconLeading ?? 'plus'));
57
+ </script>
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <FluxPressable
3
+ :component-type="type"
4
+ :class="CLASS_MAP[variant]"
5
+ type="button"
6
+ :tabindex="tabindex"
7
+ :href="href"
8
+ :rel="rel"
9
+ :target="target"
10
+ :to="to">
11
+ <slot/>
12
+
13
+ <slot
14
+ v-if="isLoading"
15
+ name="loader">
16
+ <div :class="$style.paneLoader">
17
+ <FluxSpinner/>
18
+ </div>
19
+ </slot>
20
+
21
+ <div
22
+ v-if="tag"
23
+ :class="$style.paneTag">
24
+ {{ tag }}
25
+ </div>
26
+ </FluxPressable>
27
+ </template>
28
+
29
+ <script
30
+ lang="ts"
31
+ setup>
32
+ import type { FluxPressableType, FluxTo } from '@flux-ui/types';
33
+ import FluxPressable from './FluxPressable.vue';
34
+ import FluxSpinner from './FluxSpinner.vue';
35
+ import $style from '$flux/css/component/Pane.module.scss';
36
+
37
+ const CLASS_MAP = {
38
+ default: $style.paneDefault,
39
+ flat: $style.paneFlat,
40
+ well: $style.paneWell
41
+ } as const;
42
+
43
+ const {
44
+ variant = 'default'
45
+ } = defineProps<{
46
+ readonly isLoading?: boolean;
47
+ readonly tag?: string;
48
+ readonly variant?: 'default' | 'flat' | 'well';
49
+ readonly type?: FluxPressableType;
50
+ readonly tabindex?: string | number;
51
+ readonly href?: string;
52
+ readonly rel?: string;
53
+ readonly target?: string;
54
+ readonly to?: FluxTo;
55
+ }>();
56
+
57
+ defineSlots<{
58
+ default(): any;
59
+ loader(): any;
60
+ }>();
61
+ </script>
@@ -0,0 +1,265 @@
1
+ <template>
2
+ <div
3
+ :class="$style.colorPicker"
4
+ :style="{
5
+ '--pickerBackground': saturationPickerColor
6
+ }">
7
+ <CoordinatePicker
8
+ v-model="saturationValue"
9
+ :class="$style.colorPickerSaturation"
10
+ :max="1"
11
+ :min="0"
12
+ :step="0.0005"
13
+ @dragging="onDragging"/>
14
+
15
+ <FluxFormSlider
16
+ v-model="hue"
17
+ :class="$style.colorPickerHueSlider"
18
+ is-tooltip-disabled
19
+ :max="360"
20
+ :min="0"
21
+ :step="0.1"/>
22
+
23
+ <FluxFormSlider
24
+ v-if="isAlphaEnabled"
25
+ v-model="alpha"
26
+ :class="$style.colorPickerAlphaSlider"
27
+ is-tooltip-disabled
28
+ :max="1"
29
+ :min="0"
30
+ :step="0.001"/>
31
+
32
+ <div :class="$style.colorPickerValue">
33
+ <div
34
+ :class="$style.colorPickerPreview"
35
+ :style="{
36
+ '--color': rgb
37
+ }"/>
38
+
39
+ <FluxFormField
40
+ v-if="type === 'hex'"
41
+ label="Hex">
42
+ <FluxFormInput v-model.lazy="modelValue"/>
43
+ </FluxFormField>
44
+
45
+ <template v-else-if="type === 'rgb'">
46
+ <FluxFormField label="R">
47
+ <FluxFormInput
48
+ v-model.lazy="rgbInputR"
49
+ :max="255"
50
+ :min="0"
51
+ type="number"/>
52
+ </FluxFormField>
53
+
54
+ <FluxFormField label="G">
55
+ <FluxFormInput
56
+ v-model.lazy="rgbInputG"
57
+ :max="255"
58
+ :min="0"
59
+ type="number"/>
60
+ </FluxFormField>
61
+
62
+ <FluxFormField label="B">
63
+ <FluxFormInput
64
+ v-model.lazy="rgbInputB"
65
+ :max="255"
66
+ :min="0"
67
+ type="number"/>
68
+ </FluxFormField>
69
+ </template>
70
+
71
+ <template v-else-if="type === 'hsv'">
72
+ <FluxFormField label="H">
73
+ <FluxFormInput
74
+ v-model.lazy="hsvInputH"
75
+ :max="1"
76
+ :min="0"
77
+ type="number"/>
78
+ </FluxFormField>
79
+
80
+ <FluxFormField label="S">
81
+ <FluxFormInput
82
+ v-model.lazy="hsvInputS"
83
+ :max="1"
84
+ :min="0"
85
+ type="number"/>
86
+ </FluxFormField>
87
+
88
+ <FluxFormField label="V">
89
+ <FluxFormInput
90
+ v-model.lazy="hsvInputV"
91
+ :max="1"
92
+ :min="0"
93
+ type="number"/>
94
+ </FluxFormField>
95
+ </template>
96
+
97
+ <template v-else-if="type === 'hsl'">
98
+ <FluxFormField label="H">
99
+ <FluxFormInput
100
+ v-model.lazy="hslInputH"
101
+ :max="360"
102
+ :min="0"
103
+ type="number"/>
104
+ </FluxFormField>
105
+
106
+ <FluxFormField label="S">
107
+ <FluxFormInput
108
+ v-model.lazy="hslInputS"
109
+ :max="100"
110
+ :min="0"
111
+ type="number"/>
112
+ </FluxFormField>
113
+
114
+ <FluxFormField label="L">
115
+ <FluxFormInput
116
+ v-model.lazy="hslInputL"
117
+ :max="100"
118
+ :min="0"
119
+ type="number"/>
120
+ </FluxFormField>
121
+ </template>
122
+ </div>
123
+ </div>
124
+ </template>
125
+
126
+ <script
127
+ lang="ts"
128
+ setup>
129
+ import { hexToRGB, hslToHSV, hslToRGB, hsvToHSL, hsvToRGB, rgbToHEX, rgbToHSL, rgbToHSV } from '@basmilius/utils';
130
+ import { blue500 } from '@flux-ui/internals';
131
+ import { computed, ComputedRef, ref, unref, watch } from 'vue';
132
+ import CoordinatePicker from './primitive/CoordinatePicker.vue';
133
+ import FluxFormField from './FluxFormField.vue';
134
+ import FluxFormInput from './FluxFormInput.vue';
135
+ import FluxFormSlider from './FluxFormSlider.vue';
136
+ import $style from '$flux/css/component/Color.module.scss';
137
+
138
+ const modelValue = defineModel<string | [number, number, number]>({
139
+ default: blue500
140
+ });
141
+
142
+ const {
143
+ type = 'hex'
144
+ } = defineProps<{
145
+ readonly isAlphaEnabled?: boolean;
146
+ readonly type?: 'hex' | 'rgb' | 'hsl' | 'hsv';
147
+ }>();
148
+
149
+ const alpha = ref(1);
150
+ const hsv = ref<[number, number, number]>([0, 0, 0]);
151
+ const isDragging = ref(false);
152
+
153
+ const rgb = computed(() => {
154
+ const [r, g, b] = hsvToRGB(...unref(hsv));
155
+
156
+ return `rgb(${r} ${g} ${b} / ${unref(alpha)})`;
157
+ });
158
+
159
+ const hue = computed({
160
+ get: () => unref(hsv)[0] * 360,
161
+ set: value => hsv.value = [value / 360, hsv.value[1], hsv.value[2]]
162
+ });
163
+
164
+ const saturation = computed({
165
+ get: () => unref(hsv)[1],
166
+ set: value => hsv.value = [hsv.value[0], value, hsv.value[2]]
167
+ });
168
+
169
+ const value = computed({
170
+ get: () => 1 - unref(hsv)[2],
171
+ set: value => hsv.value = [hsv.value[0], hsv.value[1], 1 - value]
172
+ });
173
+
174
+ const saturationValue = computed({
175
+ get: (): [number, number] => [unref(saturation), unref(value)],
176
+ set: ([s, v]: [number, number]) => {
177
+ saturation.value = s;
178
+ value.value = v;
179
+ }
180
+ });
181
+
182
+ const saturationPickerColor = computed(() => {
183
+ const [r, g, b] = hsvToRGB(unref(hsv)[0], 1, 1);
184
+
185
+ return `rgb(${r} ${g} ${b})`;
186
+ });
187
+
188
+ const hslInputH = generateComputedInput(0, hsvToHSL, hslToHSV);
189
+ const hslInputS = generateComputedInput(1, hsvToHSL, hslToHSV);
190
+ const hslInputL = generateComputedInput(2, hsvToHSL, hslToHSV);
191
+
192
+ const hsvInputH = generateComputedInput(0);
193
+ const hsvInputS = generateComputedInput(1);
194
+ const hsvInputV = generateComputedInput(2);
195
+
196
+ const rgbInputR = generateComputedInput(0, hsvToRGB, rgbToHSV);
197
+ const rgbInputG = generateComputedInput(1, hsvToRGB, rgbToHSV);
198
+ const rgbInputB = generateComputedInput(2, hsvToRGB, rgbToHSV);
199
+
200
+ function onDragging(is: boolean): void {
201
+ isDragging.value = is;
202
+ }
203
+
204
+ function generateComputedInput(index: number, fromHSV?: (a: number, b: number, c: number) => [number, number, number], toHSV?: (a: number, b: number, c: number) => [number, number, number]): ComputedRef<number> {
205
+ return computed({
206
+ get: () => fromHSV?.(...unref(hsv))[index] ?? unref(hsv)[index],
207
+ set: value => {
208
+ const values = fromHSV?.(...unref(hsv)) ?? unref(hsv);
209
+ values[index] = value;
210
+ hsv.value = toHSV?.(...values) ?? values;
211
+ }
212
+ });
213
+ }
214
+
215
+ watch(modelValue, (modelValue, oldModelValue) => {
216
+ if (unref(isDragging)) {
217
+ return;
218
+ }
219
+
220
+ if (JSON.stringify(modelValue) === JSON.stringify(oldModelValue)) {
221
+ return;
222
+ }
223
+
224
+ const hex = type === 'hex' ? modelValue.toString() : '';
225
+ const values: [number, number, number] = type !== 'hex' ? modelValue as [number, number, number] : [0, 0, 0];
226
+
227
+ switch (type) {
228
+ case 'hex':
229
+ hsv.value = rgbToHSV(...hexToRGB(hex));
230
+ break;
231
+
232
+ case 'rgb':
233
+ hsv.value = rgbToHSV(...values);
234
+ break;
235
+
236
+ case 'hsl':
237
+ hsv.value = rgbToHSV(...hslToRGB(...values));
238
+ break;
239
+
240
+ case 'hsv':
241
+ hsv.value = [...values];
242
+ break;
243
+ }
244
+ }, {immediate: true});
245
+
246
+ watch(hsv, hsv => {
247
+ switch (type) {
248
+ case 'hex':
249
+ modelValue.value = rgbToHEX(...hsvToRGB(...hsv));
250
+ break;
251
+
252
+ case 'rgb':
253
+ modelValue.value = hsvToRGB(...hsv);
254
+ break;
255
+
256
+ case 'hsl':
257
+ modelValue.value = rgbToHSL(...hsvToRGB(...hsv));
258
+ break;
259
+
260
+ case 'hsv':
261
+ modelValue.value = [...hsv];
262
+ break;
263
+ }
264
+ });
265
+ </script>
@@ -0,0 +1,81 @@
1
+ <template>
2
+ <div :class="$style.colorSelect">
3
+ <button
4
+ v-for="color of colors"
5
+ :class="modelValue === color ? $style.colorSelectColorSelected : $style.colorSelectColorDeselected"
6
+ :style="{
7
+ '--color': color
8
+ }"
9
+ @click="select(color)">
10
+ <FluxIcon
11
+ :class="$style.colorSelectCheck"
12
+ name="check"
13
+ :size="16"/>
14
+ </button>
15
+
16
+ <FluxFlyout v-if="isCustomAllowed">
17
+ <template #opener="{open}">
18
+ <button
19
+ :class="$style.colorSelectCustom"
20
+ @click="open()">
21
+ <FluxIcon
22
+ name="ellipsis-h"
23
+ :size="16"/>
24
+ </button>
25
+ </template>
26
+
27
+ <template #default="{close}">
28
+ <FluxColorPicker
29
+ v-model="customColor"
30
+ :class="$style.colorSelectCustomPicker"/>
31
+
32
+ <FluxPaneBody :class="$style.colorSelectButtons">
33
+ <FluxSecondaryButton
34
+ :label="t('flux.cancel')"
35
+ @click="close()"/>
36
+
37
+ <FluxPrimaryButton
38
+ :label="t('flux.ok')"
39
+ @click="select(customColor, close)"/>
40
+ </FluxPaneBody>
41
+ </template>
42
+ </FluxFlyout>
43
+ </div>
44
+ </template>
45
+
46
+ <script
47
+ lang="ts"
48
+ setup>
49
+ import { amber500, blue500, cyan500, emerald500, fuchsia500, green500, indigo500, lime500, orange500, pink500, purple500, red500, rose500, sky500, teal500, violet500, yellow500 } from '@flux-ui/internals';
50
+ import { ref, watch } from 'vue';
51
+ import { useTranslate } from '$flux/composable/private';
52
+ import FluxColorPicker from './FluxColorPicker.vue';
53
+ import FluxFlyout from './FluxFlyout.vue';
54
+ import FluxIcon from './FluxIcon.vue';
55
+ import FluxPaneBody from './FluxPaneBody.vue';
56
+ import FluxPrimaryButton from './FluxPrimaryButton.vue';
57
+ import FluxSecondaryButton from './FluxSecondaryButton.vue';
58
+ import $style from '$flux/css/component/Color.module.scss';
59
+
60
+ const modelValue = defineModel<string>({
61
+ default: '#000000'
62
+ });
63
+
64
+ const {
65
+ colors = [red500, orange500, amber500, yellow500, lime500, green500, emerald500, teal500, cyan500, sky500, blue500, indigo500, violet500, purple500, fuchsia500, pink500, rose500]
66
+ } = defineProps<{
67
+ readonly colors?: string[];
68
+ readonly isCustomAllowed?: boolean;
69
+ }>();
70
+
71
+ const t = useTranslate();
72
+
73
+ const customColor = ref('#000000');
74
+
75
+ function select(color: string, close?: () => void): void {
76
+ modelValue.value = color;
77
+ close?.();
78
+ }
79
+
80
+ watch(modelValue, value => customColor.value = value, {immediate: true});
81
+ </script>
@@ -0,0 +1,71 @@
1
+ <template>
2
+ <div
3
+ :class="clsx(
4
+ $style.comment,
5
+ isTyping && $style.isTyping,
6
+ isReceived && $style.isReceived
7
+ )"
8
+ role="article">
9
+ <FluxAvatar
10
+ :alt="avatarAlt"
11
+ :fallback="avatarFallback"
12
+ :fallback-icon="avatarFallbackIcon"
13
+ :fallback-initials="avatarFallbackInitials"
14
+ :size="42"
15
+ :src="avatarSrc"/>
16
+
17
+ <div :class="$style.commentContent">
18
+ <div
19
+ v-if="isTyping"
20
+ :class="$style.commentTyping"/>
21
+ <slot v-else/>
22
+ </div>
23
+
24
+ <div :class="$style.commentFooter">
25
+ <span v-if="isReceived && postedBy">{{ postedBy }}</span>
26
+ <time
27
+ v-if="iso && relative && !isTyping"
28
+ :datetime="iso">
29
+ {{ isJustNowVisible ? translate('flux.justNow') : relative }}
30
+ </time>
31
+ </div>
32
+ </div>
33
+ </template>
34
+
35
+ <script
36
+ lang="ts"
37
+ setup>
38
+ import type { FluxIconName } from '@flux-ui/types';
39
+ import { clsx } from 'clsx';
40
+ import type { DateTime } from 'luxon';
41
+ import { computed } from 'vue';
42
+ import { useTranslate } from '$flux/composable/private';
43
+ import FluxAvatar from './FluxAvatar.vue';
44
+ import $style from '$flux/css/component/Comment.module.scss';
45
+
46
+ const {
47
+ avatarFallback = 'colorized',
48
+ avatarFallbackIcon = 'user',
49
+ postedOn
50
+ } = defineProps<{
51
+ readonly avatarAlt?: string;
52
+ readonly avatarFallback?: 'colorized' | 'neutral';
53
+ readonly avatarFallbackIcon?: FluxIconName;
54
+ readonly avatarFallbackInitials?: string;
55
+ readonly avatarSrc?: string;
56
+ readonly isReceived?: boolean;
57
+ readonly isTyping?: boolean;
58
+ readonly postedBy?: string;
59
+ readonly postedOn?: DateTime;
60
+ }>();
61
+
62
+ defineSlots<{
63
+ default(): any;
64
+ }>();
65
+
66
+ const translate = useTranslate();
67
+
68
+ const isJustNowVisible = computed(() => postedOn && Math.abs(postedOn.diffNow().as('seconds')) < 15);
69
+ const iso = computed(() => postedOn?.toISO() ?? null);
70
+ const relative = computed(() => postedOn?.toRelative() ?? null);
71
+ </script>
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <FluxPane>
3
+ <FluxPaneHeader
4
+ :icon="confirm.icon"
5
+ :title="confirm.title"/>
6
+
7
+ <FluxPaneBody v-html="confirm.message"/>
8
+
9
+ <FluxPaneFooter>
10
+ <FluxSpacer/>
11
+
12
+ <FluxSecondaryButton
13
+ :label="translate('flux.cancel')"
14
+ @click="confirm.onCancel()"/>
15
+
16
+ <FluxPrimaryButton
17
+ icon-leading="circle-check"
18
+ :label="translate('flux.ok')"
19
+ @click="confirm.onConfirm()"/>
20
+ </FluxPaneFooter>
21
+ </FluxPane>
22
+ </template>
23
+
24
+ <script
25
+ lang="ts"
26
+ setup>
27
+ import type { FluxConfirmObject } from '@flux-ui/types';
28
+ import { useTranslate } from '$flux/composable/private';
29
+ import FluxPane from './FluxPane.vue';
30
+ import FluxPaneBody from './FluxPaneBody.vue';
31
+ import FluxPaneFooter from './FluxPaneFooter.vue';
32
+ import FluxPaneHeader from './FluxPaneHeader.vue';
33
+ import FluxPrimaryButton from './FluxPrimaryButton.vue';
34
+ import FluxSecondaryButton from './FluxSecondaryButton.vue';
35
+ import FluxSpacer from './FluxSpacer.vue';
36
+
37
+ defineProps<{
38
+ readonly confirm: FluxConfirmObject;
39
+ }>();
40
+
41
+ const translate = useTranslate();
42
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div
3
+ :class="$style.container"
4
+ :style="{'--gutter': `${gutter}px`}">
5
+ <slot/>
6
+ </div>
7
+ </template>
8
+
9
+ <script
10
+ lang="ts"
11
+ setup>
12
+ import $style from '$flux/css/component/Layout.module.scss';
13
+
14
+ const {
15
+ gutter = 30
16
+ } = defineProps<{
17
+ readonly gutter?: number;
18
+ }>();
19
+
20
+ defineSlots<{
21
+ default(): any;
22
+ }>();
23
+ </script>
@@ -0,0 +1,96 @@
1
+ <template>
2
+ <FluxTable
3
+ :is-bordered="isBordered"
4
+ :is-hoverable="isHoverable"
5
+ :is-loading="isLoading"
6
+ :is-separated="isSeparated"
7
+ :is-striped="isStriped">
8
+ <template
9
+ v-if="'header' in slots"
10
+ #header>
11
+ <FluxTableRow>
12
+ <slot
13
+ name="header"
14
+ v-bind="{page, perPage, rows, total}"/>
15
+ </FluxTableRow>
16
+ </template>
17
+
18
+ <template
19
+ v-if="'footer' in slots"
20
+ #footer>
21
+ <FluxTableRow>
22
+ <slot
23
+ name="footer"
24
+ v-bind="{page, perPage, rows, total}"/>
25
+ </FluxTableRow>
26
+ </template>
27
+
28
+ <FluxTableRow
29
+ v-for="(row, index) of rows"
30
+ :key="uniqueKey ? row[uniqueKey] : index">
31
+ <template v-for="(_, name) of slots">
32
+ <slot
33
+ v-if="name !== 'footer' && name !== 'header'"
34
+ v-bind="{index, page, perPage, row, rows, total}"
35
+ :name="name"/>
36
+ </template>
37
+ </FluxTableRow>
38
+ </FluxTable>
39
+ </template>
40
+
41
+ <script
42
+ lang="ts"
43
+ setup
44
+ generic="T extends Record<string, any>">
45
+ import { computed } from 'vue';
46
+ import FluxTable from './FluxTable.vue';
47
+ import FluxTableRow from './FluxTableRow.vue';
48
+
49
+ const {
50
+ isBordered = true,
51
+ isHoverable = false,
52
+ isLoading = false,
53
+ isSeparated = true,
54
+ isStriped = false,
55
+ dataSet,
56
+ perPage
57
+ } = defineProps<{
58
+ readonly dataSet: T[];
59
+ readonly isBordered?: boolean;
60
+ readonly isHoverable?: boolean;
61
+ readonly isLoading?: boolean;
62
+ readonly isSeparated?: boolean;
63
+ readonly isStriped?: boolean;
64
+ readonly page: number;
65
+ readonly perPage: number;
66
+ readonly total: number;
67
+ readonly uniqueKey?: string;
68
+ }>();
69
+
70
+ const slots = defineSlots<{
71
+ [key: string]: (props: {
72
+ readonly index: number;
73
+ readonly page: number;
74
+ readonly perPage: number;
75
+ readonly row: T;
76
+ readonly rows: T[];
77
+ readonly total: number;
78
+ }) => any;
79
+
80
+ footer(props: {
81
+ readonly page: number;
82
+ readonly perPage: number;
83
+ readonly rows: T[];
84
+ readonly total: number;
85
+ }): any;
86
+
87
+ header(props: {
88
+ readonly page: number;
89
+ readonly perPage: number;
90
+ readonly rows: T[];
91
+ readonly total: number;
92
+ }): any;
93
+ }>();
94
+
95
+ const rows = computed(() => dataSet.slice(0, perPage));
96
+ </script>