@steroidsjs/bootstrap 3.0.0-beta.126 → 3.0.0-beta.128

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 (28) hide show
  1. package/content/CalendarSystem/AsideCalendars/AsideCalendars.d.ts +0 -1
  2. package/content/CalendarSystem/AsideCalendars/AsideCalendars.js +1 -1
  3. package/content/CalendarSystem/CalendarSystemModalView.js +1 -1
  4. package/content/CalendarSystem/CalendarSystemView.js +22 -6
  5. package/content/CalendarSystem/ContentHeader/ContentHeader.d.ts +1 -1
  6. package/content/CalendarSystem/ContentHeader/ContentHeader.js +1 -1
  7. package/content/CalendarSystem/MonthGrid/MonthGrid.d.ts +2 -2
  8. package/content/CalendarSystem/MonthGrid/MonthGrid.js +2 -2
  9. package/content/CalendarSystem/WeekGrid/WeekGrid.d.ts +2 -2
  10. package/content/CalendarSystem/WeekGrid/WeekGrid.js +5 -5
  11. package/content/Chat/ChatView.js +2 -2
  12. package/content/Chat/views/BubbleMessage/BubbleMessageView.d.ts +1 -0
  13. package/content/Chat/views/BubbleMessage/BubbleMessageView.js +16 -1
  14. package/content/Chat/views/BubbleMessage/BubbleMessageView.scss +38 -0
  15. package/content/Chat/views/BubblesDateGroup/BubblesDateGroup.js +1 -1
  16. package/content/Chat/views/ChatFileItem/ChatFileItemView.d.ts +9 -0
  17. package/content/Chat/views/ChatFileItem/ChatFileItemView.js +50 -0
  18. package/content/Chat/views/ChatFileItem/ChatFileItemView.scss +184 -0
  19. package/content/Chat/views/ChatFileItem/index.d.ts +2 -0
  20. package/content/Chat/views/ChatFileItem/index.js +7 -0
  21. package/content/Chat/views/ChatInput/ChatInputView.d.ts +2 -6
  22. package/content/Chat/views/ChatInput/ChatInputView.js +25 -2
  23. package/content/Chat/views/ChatInput/ChatInputView.scss +46 -0
  24. package/index.d.ts +3 -0
  25. package/index.js +3 -0
  26. package/index.scss +1 -0
  27. package/package.json +2 -2
  28. package/scss/mixins/scroll.scss +6 -0
@@ -4,7 +4,6 @@ import './AsideCalendars.scss';
4
4
  interface IAsideCalendarsProps {
5
5
  eventGroups: IEventGroup[];
6
6
  eventGroupsTitle: string;
7
- selectedCalendarGroupsIds: number[];
8
7
  onChangeEventGroupsIds: (selectedIds: number[]) => void;
9
8
  openCreateEventGroupModal: () => void;
10
9
  }
@@ -36,7 +36,7 @@ function AsideCalendars(props) {
36
36
  return (react_1["default"].createElement("div", { className: bem.block() },
37
37
  react_1["default"].createElement(content_1.Accordion, null,
38
38
  react_1["default"].createElement(content_1.AccordionItem, { title: props.eventGroupsTitle },
39
- react_1["default"].createElement(form_1.CheckboxListField, { items: props.eventGroups, selectedIds: props.selectedCalendarGroupsIds, onChange: function (selectedIds) { return props.onChangeEventGroupsIds(selectedIds); } }),
39
+ react_1["default"].createElement(form_1.CheckboxListField, { items: props.eventGroups, onChange: function (selectedIds) { return props.onChangeEventGroupsIds(selectedIds); } }),
40
40
  react_1["default"].createElement(form_1.Button, { color: 'basic', className: bem.element('add'), onClick: props.openCreateEventGroupModal, size: 'sm' },
41
41
  react_1["default"].createElement(content_1.Icon, { name: "add_16x16" }))))));
42
42
  }
@@ -19,7 +19,7 @@ function CalendarSystemModalView(props) {
19
19
  var dispatch = (0, hooks_1.useDispatch)();
20
20
  var eventInitialValues = react_1["default"].useMemo(function () { return props.eventInitialValues; }, [props.eventInitialValues]);
21
21
  var callOnEventSubmit = function (fields) {
22
- return eventInitialValues && !props.isCreate ? props.onEventSubmit(fields, eventInitialValues) : props.onEventSubmit(fields);
22
+ return eventInitialValues && !props.isCreate ? props.onModalFormSubmit(fields, eventInitialValues) : props.onModalFormSubmit(fields);
23
23
  };
24
24
  var onCloseModal = react_1["default"].useCallback(function () {
25
25
  props.onClose();
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
15
  };
@@ -14,15 +25,20 @@ var MonthGrid_1 = __importDefault(require("./MonthGrid"));
14
25
  var WeekGrid_1 = __importDefault(require("./WeekGrid"));
15
26
  function CalendarSystemView(props) {
16
27
  var bem = (0, useBem_1["default"])('CalendarSystemView');
28
+ var calendarTypeGrids = react_1["default"].useMemo(function () {
29
+ var _a;
30
+ return (_a = {},
31
+ _a[CalendarType_1["default"].MONTH] = react_1["default"].createElement(MonthGrid_1["default"], __assign({}, props.monthGridProps)),
32
+ _a[CalendarType_1["default"].WEEK] = react_1["default"].createElement(WeekGrid_1["default"], __assign({}, props.weekGridProps)),
33
+ _a);
34
+ }, [props.monthGridProps, props.weekGridProps]);
17
35
  return (react_1["default"].createElement("div", { className: bem(bem.block(), props.className), style: props.style },
18
36
  react_1["default"].createElement("aside", { className: bem.element('aside') },
19
37
  react_1["default"].createElement(AsideHeader_1["default"], { onClick: props.openCreateModal, className: bem.element('aside-header') }),
20
- react_1["default"].createElement(Calendar_1["default"], { showFooter: false, onMonthChange: props.onMonthChange }),
21
- react_1["default"].createElement(AsideCalendars_1["default"], { eventGroups: props.eventGroups, eventGroupsTitle: props.eventGroupsTitle, selectedCalendarGroupsIds: props.selectedCalendarGroups, onChangeEventGroupsIds: props.onChangeEventGroupsIds, openCreateEventGroupModal: props.openCreateEventGroupModal })),
38
+ react_1["default"].createElement(Calendar_1["default"], { showFooter: false, onMonthChange: props.onInnerCalendarChangeMonth }),
39
+ react_1["default"].createElement(AsideCalendars_1["default"], { eventGroups: props.eventGroups, eventGroupsTitle: props.eventGroupsTitle, onChangeEventGroupsIds: props.onChangeEventGroupsIds, openCreateEventGroupModal: props.openCreateEventGroupModal })),
22
40
  react_1["default"].createElement("div", { className: bem.element('content') },
23
- react_1["default"].createElement(ContentHeader_1["default"], { dateToDisplay: props.dateToDisplay, onChangeCalendarType: props.onChangeCalendarType, applyControl: props.applyControl }),
24
- props.calendarType === CalendarType_1["default"].MONTH
25
- ? (react_1["default"].createElement(MonthGrid_1["default"], { monthCalendarDays: props.monthCalendarDays, getEventsFromDate: props.getEventsFromDate, weekDays: props.weekDays, openEditModal: props.openEditModal, openCreateModal: props.openCreateModal }))
26
- : (react_1["default"].createElement(WeekGrid_1["default"], { allHours: props.allHours, getEventsFromDate: props.getEventsFromDate, currentWeekDays: props.currentWeekDays, openEditModal: props.openEditModal, openCreateModal: props.openCreateModal })))));
41
+ react_1["default"].createElement(ContentHeader_1["default"], { dateToDisplay: props.dateToDisplay, onChangeCalendarType: props.handleCalendarTypeChange, handleControlClick: props.handleControlClick }),
42
+ calendarTypeGrids[props.calendarType])));
27
43
  }
28
44
  exports["default"] = CalendarSystemView;
@@ -3,7 +3,7 @@ import './ContentHeader.scss';
3
3
  interface IContentHeaderProps {
4
4
  dateToDisplay: string;
5
5
  onChangeCalendarType: (newType: string) => void;
6
- applyControl: (event: React.MouseEvent<HTMLElement>) => void;
6
+ handleControlClick: (event: React.MouseEvent<HTMLElement>) => void;
7
7
  }
8
8
  declare function ContentHeader(props: IContentHeaderProps): JSX.Element;
9
9
  declare const _default: React.MemoExoticComponent<typeof ContentHeader>;
@@ -16,7 +16,7 @@ function ContentHeader(props) {
16
16
  var bem = (0, useBem_1["default"])('ContentHeader');
17
17
  return (react_1["default"].createElement("div", { className: bem.block() },
18
18
  react_1["default"].createElement(Text_1["default"], { content: props.dateToDisplay, className: bem.element('month') }),
19
- react_1["default"].createElement("ul", { className: bem.element('controls'), onClick: props.applyControl }, Object.entries(DateControlType_1["default"].getIcons()).map(function (_a, controlIndex) {
19
+ react_1["default"].createElement("ul", { className: bem.element('controls'), onClick: props.handleControlClick }, Object.entries(DateControlType_1["default"].getIcons()).map(function (_a, controlIndex) {
20
20
  var controlLabel = _a[0], controlIcon = _a[1];
21
21
  return (react_1["default"].createElement("li", { key: controlIndex, className: bem.element('controls-item'), "data-control": controlLabel },
22
22
  react_1["default"].createElement(content_1.Icon, { className: bem.element('controls-item-icon'), name: controlIcon })));
@@ -3,9 +3,9 @@ import { IDay, IEvent } from '@steroidsjs/core/ui/content/CalendarSystem/Calenda
3
3
  import CalendarEnum from '@steroidsjs/core/ui/content/CalendarSystem/enums/CalendarType';
4
4
  import './MonthGrid.scss';
5
5
  interface IMonthGridProps {
6
- monthCalendarDays: IDay[];
6
+ monthGridWeekDays: string[];
7
+ monthGridCalendarDays: IDay[];
7
8
  getEventsFromDate: (dateFromDay: Date, currentCalendarType: CalendarEnum) => IEvent[];
8
- weekDays: string[];
9
9
  openEditModal: (event: IEvent) => void;
10
10
  openCreateModal: (eventInitialDay?: IDay) => void;
11
11
  }
@@ -33,7 +33,7 @@ var MonthDay_1 = __importDefault(require("./views/MonthDay"));
33
33
  function MonthGrid(props) {
34
34
  var bem = (0, useBem_1["default"])('MonthGrid');
35
35
  return (react_1["default"].createElement("div", { className: bem.block() },
36
- react_1["default"].createElement("div", { className: bem.element('week-days') }, props.weekDays.map(function (day, dayIndex) { return (react_1["default"].createElement("span", { key: dayIndex, className: bem.element('week-days-day') }, day)); })),
37
- react_1["default"].createElement("div", { className: bem.element('grid') }, props.monthCalendarDays.map(function (day, dayIndex) { return (react_1["default"].createElement(MonthDay_1["default"], { key: dayIndex, openEditModal: props.openEditModal, getEventsFromDate: props.getEventsFromDate, openCreateModal: props.openCreateModal, day: day })); }))));
36
+ react_1["default"].createElement("div", { className: bem.element('week-days') }, props.monthGridWeekDays.map(function (day, dayIndex) { return (react_1["default"].createElement("span", { key: dayIndex, className: bem.element('week-days-day') }, day)); })),
37
+ react_1["default"].createElement("div", { className: bem.element('grid') }, props.monthGridCalendarDays.map(function (day, dayIndex) { return (react_1["default"].createElement(MonthDay_1["default"], { key: dayIndex, openEditModal: props.openEditModal, getEventsFromDate: props.getEventsFromDate, openCreateModal: props.openCreateModal, day: day })); }))));
38
38
  }
39
39
  exports["default"] = (0, react_1.memo)(MonthGrid);
@@ -3,8 +3,8 @@ import { IDay, IEvent } from '@steroidsjs/core/ui/content/CalendarSystem/Calenda
3
3
  import CalendarEnum from '@steroidsjs/core/ui/content/CalendarSystem/enums/CalendarType';
4
4
  import './WeekGrid.scss';
5
5
  interface IWeekGridProps {
6
- currentWeekDays: IDay[];
7
- allHours: string[];
6
+ weekGridTwentyFourHoursArray: string[];
7
+ weekGridCurrentWeekDays: IDay[];
8
8
  getEventsFromDate: (dateFromDay: Date, currentCalendarType: CalendarEnum) => IEvent[];
9
9
  openEditModal: (event: IEvent) => void;
10
10
  openCreateModal: (eventInitialDay?: IDay) => void;
@@ -10,16 +10,16 @@ var WeekHour_1 = __importDefault(require("./views/WeekHour"));
10
10
  require("./WeekGrid.scss");
11
11
  function WeekGrid(props) {
12
12
  var bem = (0, useBem_1["default"])('WeekGrid');
13
- var currentWeekDays = props.currentWeekDays, getEventsFromDate = props.getEventsFromDate;
14
- var renderWeekHours = react_1["default"].useCallback(function (hour) { return currentWeekDays.map(function (dayOfWeek, dayOfWeekIndex) { return (react_1["default"].createElement(WeekHour_1["default"], { hour: hour, getEventsFromDate: getEventsFromDate, key: dayOfWeekIndex, dayOfWeek: dayOfWeek, openEditModal: props.openEditModal, openCreateModal: props.openCreateModal })); }); }, [currentWeekDays, getEventsFromDate, props.openCreateModal, props.openEditModal]);
13
+ var weekGridCurrentWeekDays = props.weekGridCurrentWeekDays, getEventsFromDate = props.getEventsFromDate;
14
+ var renderWeekHours = react_1["default"].useCallback(function (hour) { return weekGridCurrentWeekDays.map(function (dayOfWeek, dayOfWeekIndex) { return (react_1["default"].createElement(WeekHour_1["default"], { hour: hour, getEventsFromDate: getEventsFromDate, key: dayOfWeekIndex, dayOfWeek: dayOfWeek, openEditModal: props.openEditModal, openCreateModal: props.openCreateModal })); }); }, [weekGridCurrentWeekDays, getEventsFromDate, props.openCreateModal, props.openEditModal]);
15
15
  return (react_1["default"].createElement("div", { className: bem.block() },
16
16
  react_1["default"].createElement("div", { className: bem.element('content') },
17
- react_1["default"].createElement("div", { className: bem.element('hours-time') }, props.allHours.map(function (hour, hourIndex) { return (react_1["default"].createElement("div", { key: hourIndex, className: bem.element('hours-time-item') }, hour)); })),
17
+ react_1["default"].createElement("div", { className: bem.element('hours-time') }, props.weekGridTwentyFourHoursArray.map(function (hour, hourIndex) { return (react_1["default"].createElement("div", { key: hourIndex, className: bem.element('hours-time-item') }, hour)); })),
18
18
  react_1["default"].createElement("div", { className: bem.element('table') },
19
- react_1["default"].createElement("div", { className: bem.element('table-heading') }, currentWeekDays.map(function (weekDay, weekDayIndex) { return (react_1["default"].createElement(Text_1["default"], { key: weekDayIndex, className: bem.element('day', {
19
+ react_1["default"].createElement("div", { className: bem.element('table-heading') }, weekGridCurrentWeekDays.map(function (weekDay, weekDayIndex) { return (react_1["default"].createElement(Text_1["default"], { key: weekDayIndex, className: bem.element('day', {
20
20
  isToday: weekDay.isToday
21
21
  }) },
22
22
  react_1["default"].createElement("span", { className: bem.element('day-wrapper') }, weekDay.formattedDisplay))); })),
23
- react_1["default"].createElement("div", { className: bem.element('table-grid') }, props.allHours.map(function (hour, hourIndex) { return (react_1["default"].createElement("div", { key: hourIndex, className: bem.element('table-grid-row') }, renderWeekHours(hour))); }))))));
23
+ react_1["default"].createElement("div", { className: bem.element('table-grid') }, props.weekGridTwentyFourHoursArray.map(function (hour, hourIndex) { return (react_1["default"].createElement("div", { key: hourIndex, className: bem.element('table-grid-row') }, renderWeekHours(hour))); }))))));
24
24
  }
25
25
  exports["default"] = react_1["default"].memo(WeekGrid);
@@ -28,10 +28,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  exports.__esModule = true;
29
29
  var react_1 = __importStar(require("react"));
30
30
  var useBem_1 = __importDefault(require("@steroidsjs/core/hooks/useBem"));
31
- var ChatInput_1 = __importDefault(require("./views/ChatInput"));
32
31
  var BubblesDateGroup_1 = __importDefault(require("./views/BubblesDateGroup"));
33
32
  function ChatView(props) {
34
33
  var bem = (0, useBem_1["default"])('ChatView');
34
+ // Scroll to bottom on new message
35
35
  var wrapperRef = (0, react_1.useRef)(null);
36
36
  var contentRef = (0, react_1.useRef)(null);
37
37
  var prevContentHeightRef = (0, react_1.useRef)(null);
@@ -57,6 +57,6 @@ function ChatView(props) {
57
57
  }))))); }, [bem, props.groupedMessagesByDates, props.currentUser]);
58
58
  return (react_1["default"].createElement("div", { className: bem.block() },
59
59
  renderChatScreen(),
60
- react_1["default"].createElement(ChatInput_1["default"], { chatId: props.chatId, onSendMessage: props.onSendMessage })));
60
+ props.renderChatInput()));
61
61
  }
62
62
  exports["default"] = ChatView;
@@ -10,6 +10,7 @@ interface IBubbleMessageProps {
10
10
  isFirstMessage?: boolean;
11
11
  isLastMessage?: boolean;
12
12
  isTodayMessage?: boolean;
13
+ files?: any[];
13
14
  }
14
15
  declare function BubbleMessageView(props: IBubbleMessageProps): JSX.Element;
15
16
  declare const _default: React.MemoExoticComponent<typeof BubbleMessageView>;
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
14
  if (k2 === undefined) k2 = k;
4
15
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -28,6 +39,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
39
  exports.__esModule = true;
29
40
  var react_1 = __importStar(require("react"));
30
41
  var react_use_1 = require("react-use");
42
+ var isEmpty_1 = __importDefault(require("lodash-es/isEmpty"));
31
43
  var useBem_1 = __importDefault(require("@steroidsjs/core/hooks/useBem"));
32
44
  var Avatar_1 = require("@steroidsjs/core/ui/content/Avatar");
33
45
  var typography_1 = require("@steroidsjs/core/ui/typography");
@@ -36,18 +48,21 @@ var Icon_1 = __importDefault(require("@steroidsjs/core/ui/content/Icon"));
36
48
  var timeTemplatesAndUnits_1 = require("@steroidsjs/core/ui/content/Chat/constants/timeTemplatesAndUnits");
37
49
  var utils_1 = require("@steroidsjs/core/ui/content/Chat/utils");
38
50
  require("./BubbleMessageView.scss");
51
+ var ChatFileItem_1 = __importDefault(require("../ChatFileItem"));
39
52
  function BubbleMessageView(props) {
40
53
  var _a, _b;
41
54
  var bem = (0, useBem_1["default"])('BubbleMessageView');
55
+ var isMessageByAnotherUser = !props.isCurrentUser;
42
56
  var _c = (0, react_1.useState)(props.timeAgo), timeAgo = _c[0], setTimeAgo = _c[1];
43
57
  (0, react_use_1.useInterval)(function () { return setTimeAgo((0, utils_1.calculateMessageTimeAgo)(props.timestamp)); }, props.isTodayMessage ? timeTemplatesAndUnits_1.SECONDS_IN_MINUTE_VALUE : null);
44
58
  return (react_1["default"].createElement("div", { className: bem.block({
45
- 'another-user': !props.isCurrentUser,
59
+ 'another-user': isMessageByAnotherUser,
46
60
  'last-message': !!props.isLastMessage
47
61
  }) },
48
62
  react_1["default"].createElement("div", { className: bem.element('user-message') },
49
63
  !props.isCurrentUser && props.isFirstMessage && (react_1["default"].createElement(Title_1["default"], { className: bem.element('username'), type: 'h4', tag: 'h4', content: "".concat(props.user.firstName, " ").concat(props.user.lastName) })),
50
64
  react_1["default"].createElement(typography_1.Text, { className: bem.element('text'), type: "body", content: props.text }),
65
+ !(0, isEmpty_1["default"])(props.files) && (react_1["default"].createElement("div", { className: bem.element('files') }, props.files.map(function (file) { return (react_1["default"].createElement(ChatFileItem_1["default"], __assign({ key: file.uid, isFileByAnotherUser: isMessageByAnotherUser, isFileFromMessage: true }, file))); }))),
51
66
  react_1["default"].createElement("div", { className: bem.element('indicators') },
52
67
  react_1["default"].createElement(typography_1.Text, { className: bem.element('time'), type: "body3", content: timeAgo }),
53
68
  props.isCurrentUser && (react_1["default"].createElement(Icon_1["default"], { className: bem.element('check'), name: "done-all" })))),
@@ -36,6 +36,18 @@ $another-user-bubble-border-color: var(--another-user-bubble-border-color);
36
36
  $another-user-message-text-color: var(--another-user-message-text-color);
37
37
  $another-user-message-time-color: var(--another-user-message-time-color);
38
38
 
39
+ @mixin svg-color($color) {
40
+ svg {
41
+ path {
42
+ stroke: $color;
43
+ }
44
+
45
+ circle {
46
+ fill: $color;
47
+ }
48
+ }
49
+ }
50
+
39
51
  .BubbleMessageView {
40
52
  $root: &;
41
53
 
@@ -72,6 +84,14 @@ $another-user-message-time-color: var(--another-user-message-time-color);
72
84
  color: $another-user-message-text-color;
73
85
  }
74
86
 
87
+ #{$root}__files {
88
+ @include svg-color($another-user-message-text-color);
89
+
90
+ .TextView {
91
+ color: $another-user-message-text-color;
92
+ }
93
+ }
94
+
75
95
  #{$root}__time {
76
96
  color: $another-user-message-time-color;
77
97
  }
@@ -140,6 +160,20 @@ $another-user-message-time-color: var(--another-user-message-time-color);
140
160
  color: $message-text-color;
141
161
  }
142
162
 
163
+ &__files {
164
+ @include svg-color($message-text-color);
165
+
166
+ display: flex;
167
+ flex-flow: column nowrap;
168
+ gap: 8px;
169
+ width: 100%;
170
+ padding: 8px 0;
171
+
172
+ .TextView {
173
+ color: $message-text-color;
174
+ }
175
+ }
176
+
143
177
  &__indicators {
144
178
  display: flex;
145
179
  flex-flow: row nowrap;
@@ -154,4 +188,8 @@ $another-user-message-time-color: var(--another-user-message-time-color);
154
188
  &__check {
155
189
  margin-left: 4px;
156
190
  }
191
+
192
+ .ChatFileItemView {
193
+ width: 100%;
194
+ }
157
195
  }
@@ -34,7 +34,7 @@ require("./BubblesDateGroup.scss");
34
34
  function BubblesDateGroup(props) {
35
35
  var _a;
36
36
  var bem = (0, useBem_1["default"])('BubblesDateGroup');
37
- var toBubbles = (0, react_1.useCallback)(function (groupedMessages) { return (react_1["default"].createElement("div", { className: bem.element('bubbles') }, groupedMessages.map(function (bubbleMessage) { return (react_1["default"].createElement(BubbleMessage_1["default"], { key: bubbleMessage.id, user: bubbleMessage.user, text: bubbleMessage.text, timestamp: bubbleMessage.timestamp, timeAgo: (0, utils_1.calculateMessageTimeAgo)(bubbleMessage.timestamp), isTodayMessage: (0, utils_1.isTodayMessage)(bubbleMessage.timestamp), isCurrentUser: bubbleMessage.user.id === props.currentUser.id, isFirstMessage: bubbleMessage.isFirstMessage, isLastMessage: bubbleMessage.isLastMessage })); }))); }, [bem, props.currentUser.id]);
37
+ var toBubbles = (0, react_1.useCallback)(function (groupedMessages) { return (react_1["default"].createElement("div", { className: bem.element('bubbles') }, groupedMessages.map(function (bubbleMessage) { return (react_1["default"].createElement(BubbleMessage_1["default"], { key: bubbleMessage.id, user: bubbleMessage.user, text: bubbleMessage.text, files: bubbleMessage.files, timestamp: bubbleMessage.timestamp, timeAgo: (0, utils_1.calculateMessageTimeAgo)(bubbleMessage.timestamp), isTodayMessage: (0, utils_1.isTodayMessage)(bubbleMessage.timestamp), isCurrentUser: bubbleMessage.user.id === props.currentUser.id, isFirstMessage: bubbleMessage.isFirstMessage, isLastMessage: bubbleMessage.isLastMessage })); }))); }, [bem, props.currentUser.id]);
38
38
  var renderDate = (0, react_1.useCallback)(function () { return (react_1["default"].createElement(react_1["default"].Fragment, null,
39
39
  react_1["default"].createElement("div", { className: bem.element('date') },
40
40
  react_1["default"].createElement("div", { className: bem.element('date-wrapper') },
@@ -0,0 +1,9 @@
1
+ import { IFileFieldItemViewProps } from '@steroidsjs/core/ui/form/FileField/FileField';
2
+ import { IMessageFile } from '@steroidsjs/core/ui/content/Chat/Chat';
3
+ import './ChatFileItemView.scss';
4
+ interface IChatFileItemViewProps extends IFileFieldItemViewProps, IMessageFile {
5
+ isFileFromMessage?: boolean;
6
+ isFileByAnotherUser?: boolean;
7
+ }
8
+ export default function ChatFileItemView(props: IChatFileItemViewProps): JSX.Element;
9
+ export {};
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ exports.__esModule = true;
6
+ var react_1 = __importDefault(require("react"));
7
+ var hooks_1 = require("@steroidsjs/core/hooks");
8
+ var Icon_1 = __importDefault(require("@steroidsjs/core/ui/content/Icon"));
9
+ var typography_1 = require("@steroidsjs/core/ui/typography");
10
+ var format_1 = require("@steroidsjs/core/ui/format");
11
+ require("./ChatFileItemView.scss");
12
+ function ChatFileItemView(props) {
13
+ var _a, _b;
14
+ var bem = (0, hooks_1.useBem)('ChatFileItemView');
15
+ var isLoading = props.progress && props.progress.percent !== 100;
16
+ var renderLink = react_1["default"].useCallback(function () {
17
+ var _a;
18
+ return (react_1["default"].createElement("a", { className: bem.element('link'), title: props.title, href: props.error ? '#' : (props.url || ((_a = props.item) === null || _a === void 0 ? void 0 : _a.url)), target: 'blank' }, props.title));
19
+ }, [bem, props.title, props.error, props.url, (_a = props.item) === null || _a === void 0 ? void 0 : _a.url]);
20
+ var renderProgressBar = react_1["default"].useCallback(function () { return (react_1["default"].createElement("div", { className: bem.element('progress-track') },
21
+ react_1["default"].createElement("div", { className: bem.element('progress-bar'), style: { width: "".concat(props.progress.percent, "%") } }))); }, [bem, props.progress]);
22
+ var renderLoadingState = react_1["default"].useCallback(function () { return (react_1["default"].createElement("div", { className: bem.element('left') },
23
+ react_1["default"].createElement("div", { className: bem.element('icon-wrapper', 'loading') },
24
+ react_1["default"].createElement(Icon_1["default"], { className: bem.element('icon-loading'), name: 'loading_default' })),
25
+ react_1["default"].createElement("div", { className: bem.element('content') },
26
+ react_1["default"].createElement("span", { className: bem.element('title', 'loading') }, props.title),
27
+ renderProgressBar()))); }, [bem, props.title, renderProgressBar]);
28
+ var renderFileItem = react_1["default"].useCallback(function () {
29
+ var _a;
30
+ return (react_1["default"].createElement("div", { className: bem.element('left') },
31
+ react_1["default"].createElement("div", { className: bem.element('icon-wrapper') },
32
+ react_1["default"].createElement(Icon_1["default"], { className: bem.element('icon'), name: (((_a = props.item) === null || _a === void 0 ? void 0 : _a.fullHeight) || props.fullHeight) ? 'img_box' : 'file_dock' })),
33
+ react_1["default"].createElement("div", { className: bem.element('content') },
34
+ react_1["default"].createElement(typography_1.Text, { type: 'boldSpan', content: props.title, className: bem.element('title') }),
35
+ renderLink(),
36
+ react_1["default"].createElement(typography_1.Text, { type: 'body2', className: bem.element('size'), color: 'light' },
37
+ react_1["default"].createElement(format_1.FileSize, { value: props.size, showZero: true })))));
38
+ }, [bem, props.fullHeight, (_b = props.item) === null || _b === void 0 ? void 0 : _b.fullHeight, props.size, props.title, renderLink]);
39
+ return (react_1["default"].createElement("div", { className: bem.block({
40
+ error: !props.isFileFromMessage && !!props.error,
41
+ isFileFromMessage: props.isFileFromMessage,
42
+ isFileForUploading: !props.isFileFromMessage,
43
+ 'another-user': !!props.isFileByAnotherUser
44
+ }) },
45
+ isLoading
46
+ ? renderLoadingState()
47
+ : renderFileItem(),
48
+ props.isFileFromMessage ? (react_1["default"].createElement(Icon_1["default"], { name: 'import', className: bem.element('download'), onClick: function () { return window.open(props.downloadUrl || props.url); } })) : (react_1["default"].createElement(Icon_1["default"], { name: props.customRemoveIcon || 'cross_8x8', className: bem.element('remove', { isLoading: isLoading }), onClick: props.onRemove }))));
49
+ }
50
+ exports["default"] = ChatFileItemView;
@@ -0,0 +1,184 @@
1
+ @use "../../../../scss/variables";
2
+ @use "../../../../scss/mixins";
3
+ @use "../../../../scss/animations" as anim;
4
+
5
+ :root {
6
+ --file-size-color: rgba(255, 255, 255, 0.60);
7
+ --file-icon-color: rgb(0, 0, 0);
8
+ --another-user-file-size-color: rgba(0, 0, 0, 0.60);
9
+ }
10
+
11
+ html[data-theme="dark"] {
12
+ --file-size-color: rgba(255, 255, 255, 0.60);
13
+ --file-icon-color: #fff;
14
+ --another-user-file-size-color: rgba(255, 255, 255, 0.60);
15
+ }
16
+
17
+ $file-size-color: var(--file-size-color);
18
+ $file-icon-color: var(--file-icon-color);
19
+ $another-user-file-size-color: var(--another-user-file-size-color);
20
+
21
+ @mixin svg-color($color) {
22
+ svg {
23
+ path {
24
+ stroke: $color;
25
+ }
26
+
27
+ circle {
28
+ fill: $color;
29
+ }
30
+ }
31
+ }
32
+
33
+ @mixin textEllipsis {
34
+ max-width: 100%;
35
+ text-overflow: ellipsis;
36
+ overflow: hidden;
37
+ display: -webkit-box;
38
+ -webkit-line-clamp: 1;
39
+ -webkit-box-orient: vertical;
40
+ }
41
+
42
+ @mixin text {
43
+ font-size: 14px;
44
+ font-style: normal;
45
+ font-weight: 700;
46
+ line-height: 18px;
47
+ }
48
+
49
+ .ChatFileItemView {
50
+ $root: &;
51
+
52
+ position: relative;
53
+ display: flex;
54
+ justify-content: space-between;
55
+ align-items: center;
56
+ column-gap: 8px;
57
+ padding: 8px;
58
+ border: 1px solid variables.$gray;
59
+ border-radius: 12px;
60
+ min-width: 320px;
61
+ width: 320px;
62
+
63
+ &_isFileFromMessage {
64
+ padding: 0;
65
+ border: none;
66
+ width: 100%;
67
+ }
68
+
69
+ &_isFileForUploading {
70
+ @include svg-color($file-icon-color);
71
+ }
72
+
73
+ &__icon-wrapper {
74
+ min-width: 24px;
75
+ min-height: 24px;
76
+ width: 24px;
77
+ height: 24px;
78
+ }
79
+
80
+ &__left {
81
+ display: flex;
82
+ align-items: center;
83
+ column-gap: 8px;
84
+ width: 100%;
85
+ }
86
+
87
+ &__content {
88
+ display: flex;
89
+ flex-flow: column nowrap;
90
+ //width: 100%;
91
+ }
92
+
93
+ &__title {
94
+ @include text;
95
+ @include textEllipsis;
96
+
97
+ display: none;
98
+
99
+ &_loading {
100
+ display: block;
101
+ }
102
+ }
103
+
104
+ &__link {
105
+ @include text;
106
+ @include textEllipsis;
107
+
108
+ &:hover {
109
+ text-decoration: underline;
110
+ }
111
+ }
112
+
113
+ &__title,
114
+ &__size {
115
+ margin-bottom: 0;
116
+ }
117
+
118
+ &__size {
119
+ font-size: 12px;
120
+ font-weight: 400;
121
+ line-height: 16px;
122
+ color: $another-user-file-size-color;
123
+ }
124
+
125
+ &_another-user {
126
+ #{$root}__size {
127
+ color: $another-user-file-size-color !important;
128
+ }
129
+ }
130
+
131
+ &_error {
132
+ @include mixins.svg-color(variables.$danger);
133
+
134
+ #{$root}__icon {
135
+ circle {
136
+ fill: variables.$danger;
137
+ }
138
+ }
139
+
140
+ #{$root}__title,
141
+ #{$root}__size {
142
+ color: variables.$danger;
143
+ }
144
+
145
+ a,
146
+ a:hover {
147
+ color: variables.$danger;
148
+ cursor: default;
149
+ pointer-events: none;
150
+ }
151
+ }
152
+
153
+ &__remove,
154
+ &__download {
155
+ cursor: pointer;
156
+ z-index: 3;
157
+ height: 25px;
158
+
159
+ svg {
160
+ min-width: 24px;
161
+ min-height: 24px;
162
+ }
163
+ }
164
+
165
+ &__icon-loading {
166
+ @include anim.loadingAnimation;
167
+ display: block;
168
+ width: 24px;
169
+ height: 24px;
170
+ }
171
+
172
+ &__progress-track {
173
+ margin-top: 4px;
174
+ height: 4px;
175
+ background-color: variables.$gray;
176
+ border-radius: 4px;
177
+ }
178
+
179
+ &__progress-bar {
180
+ height: inherit;
181
+ background-color: variables.$primary;
182
+ border-radius: 4px;
183
+ }
184
+ }
@@ -0,0 +1,2 @@
1
+ import ChatFileItemView from './ChatFileItemView';
2
+ export default ChatFileItemView;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ exports.__esModule = true;
6
+ var ChatFileItemView_1 = __importDefault(require("./ChatFileItemView"));
7
+ exports["default"] = ChatFileItemView_1["default"];
@@ -1,7 +1,3 @@
1
+ import { IChatInputViewProps } from '@steroidsjs/core/ui/content/Chat/Chat';
1
2
  import './ChatInputView.scss';
2
- interface IChatInputProps {
3
- chatId: string;
4
- onSendMessage: (data: any) => void;
5
- }
6
- export default function ChatInputView(props: IChatInputProps): JSX.Element;
7
- export {};
3
+ export default function ChatInputView(props: IChatInputViewProps): JSX.Element;
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
14
  if (k2 === undefined) k2 = k;
4
15
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -29,13 +40,25 @@ exports.__esModule = true;
29
40
  var react_1 = __importStar(require("react"));
30
41
  var useBem_1 = __importDefault(require("@steroidsjs/core/hooks/useBem"));
31
42
  var form_1 = require("@steroidsjs/core/ui/form");
43
+ var ButtonView_1 = __importDefault(require("../../../../form/Button/ButtonView"));
44
+ var ChatFileItem_1 = __importDefault(require("../ChatFileItem"));
32
45
  require("./ChatInputView.scss");
46
+ var HiddenUploadFileButton = (0, react_1.forwardRef)(function (props, ref) { return (react_1["default"].createElement("button", __assign({ type: 'button', ref: ref }, props))); });
33
47
  function ChatInputView(props) {
34
48
  var bem = (0, useBem_1["default"])('ChatInputView');
49
+ var filePickerRef = (0, react_1.useRef)(null);
50
+ var onBrowseFile = (0, react_1.useCallback)(function (e) {
51
+ e.preventDefault();
52
+ filePickerRef.current.click();
53
+ }, [filePickerRef]);
35
54
  var renderInputActions = (0, react_1.useCallback)(function () { return (react_1["default"].createElement("div", { className: bem.element('actions') },
36
- react_1["default"].createElement(form_1.Button, { className: bem.element('action'), icon: "send", type: "submit" }))); }, [bem]);
55
+ react_1["default"].createElement(ButtonView_1["default"], { className: bem.element('action'), icon: "clip", onClick: onBrowseFile }),
56
+ react_1["default"].createElement(ButtonView_1["default"], { className: bem.element('action'), icon: "send", type: "submit" }))); }, [bem, onBrowseFile]);
37
57
  return (react_1["default"].createElement("div", { className: bem.block() },
38
58
  react_1["default"].createElement(form_1.Form, { formId: props.chatId, className: bem.element('form'), onSubmit: props.onSendMessage, useRedux: true },
39
- react_1["default"].createElement(form_1.InputField, { className: bem.element('input'), attribute: "text", size: "lg", required: true, placeholder: __('Введите сообщение'), addonAfter: renderInputActions() }))));
59
+ react_1["default"].createElement(form_1.InputField, { className: bem.element('input'), attribute: "text", size: "lg", placeholder: props.inputPlaceholder, addonAfter: renderInputActions() }),
60
+ react_1["default"].createElement(form_1.FileField, __assign({ className: bem.element('files'), attribute: 'filesId', itemView: ChatFileItem_1["default"], buttonView: HiddenUploadFileButton, buttonProps: {
61
+ ref: filePickerRef
62
+ }, multiple: false, showRemove: true, onChange: props.onUploadFiles }, props.fileFieldProps)))));
40
63
  }
41
64
  exports["default"] = ChatInputView;
@@ -1,4 +1,18 @@
1
1
  @use "../../../../scss/variables";
2
+ @use "../../../../scss/mixins";
3
+
4
+ :root {
5
+ --sidebar-scroll-thumb-color: #cbd5db;
6
+ --sidebar-scroll-track-color: rgba(0, 0, 0, 0.04);
7
+ }
8
+
9
+ html[data-theme="dark"] {
10
+ --sidebar-scroll-thumb-color: #4B4E5E;
11
+ --sidebar-scroll-track-color: #272A37;
12
+ }
13
+
14
+ $sidebar-scroll-thumb-color: var(--sidebar-scroll-thumb-color);
15
+ $sidebar-scroll-track-color: var(--sidebar-scroll-track-color);
2
16
 
3
17
  .ChatInputView {
4
18
  &__actions {
@@ -33,4 +47,36 @@
33
47
  padding: 0;
34
48
  }
35
49
  }
50
+
51
+ &__form {
52
+ >* {
53
+ margin-bottom: 8px;
54
+ }
55
+ }
56
+
57
+ .FileFieldView__button {
58
+ position: absolute;
59
+ opacity: 0;
60
+ height: 0;
61
+ width: 0;
62
+ line-height: 0;
63
+ overflow: hidden;
64
+ padding: 0;
65
+ margin: 0;
66
+ border: 0;
67
+ }
68
+
69
+ &__files .FileFieldView__files {
70
+ flex-flow: row nowrap;
71
+ overflow: auto;
72
+ gap: 8px;
73
+ padding-bottom: 8px;
74
+ margin-bottom: 0;
75
+
76
+ @include mixins.horizontalScrollWrapper(8px, $sidebar-scroll-thumb-color, $sidebar-scroll-track-color);
77
+
78
+ &::-webkit-scrollbar {
79
+ width: 4px;
80
+ }
81
+ }
36
82
  }
package/index.d.ts CHANGED
@@ -62,6 +62,9 @@ declare const _default: {
62
62
  'content.ChatView': {
63
63
  lazy: () => any;
64
64
  };
65
+ 'content.ChatInputView': {
66
+ lazy: () => any;
67
+ };
65
68
  'form.AutoCompleteFieldView': {
66
69
  lazy: () => any;
67
70
  };
package/index.js CHANGED
@@ -65,6 +65,9 @@ exports["default"] = {
65
65
  'content.ChatView': {
66
66
  lazy: function () { return require('./content/Chat/ChatView')["default"]; }
67
67
  },
68
+ 'content.ChatInputView': {
69
+ lazy: function () { return require('./content/Chat/views/ChatInput/ChatInputView')["default"]; }
70
+ },
68
71
  'form.AutoCompleteFieldView': {
69
72
  lazy: function () { return require('./form/AutoCompleteField/AutoCompleteFieldView')["default"]; }
70
73
  },
package/index.scss CHANGED
@@ -32,6 +32,7 @@
32
32
  @include meta.load-css('content/Kanban/views/KanbanTask/KanbanTaskView');
33
33
  @include meta.load-css('content/Kanban/views/KanbanModal/KanbanModalView');
34
34
  @include meta.load-css('content/Chat/ChatView');
35
+ @include meta.load-css('content/Chat/views/ChatInput/ChatInputView');
35
36
  @include meta.load-css('crud/Crud/CrudView');
36
37
  @include meta.load-css('form/AutoCompleteField/AutoCompleteFieldView');
37
38
  @include meta.load-css('form/Button/ButtonView');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steroidsjs/bootstrap",
3
- "version": "3.0.0-beta.126",
3
+ "version": "3.0.0-beta.128",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "author": "Vladimir Kozhin <hello@kozhindev.com>",
@@ -37,7 +37,7 @@
37
37
  "react-use": "^17.4.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@steroidsjs/core": "^3.0 || >=3.0.0-beta.111",
40
+ "@steroidsjs/core": "^3.0 || >=3.0.0-beta.117",
41
41
  "@steroidsjs/eslint-config": "^2.1.4",
42
42
  "@types/enzyme": "^3.10.8",
43
43
  "@types/googlemaps": "^3.43.3",
@@ -29,3 +29,9 @@
29
29
  max-height: $maxHeight;
30
30
  overflow: auto;
31
31
  }
32
+
33
+ @mixin horizontalScrollWrapper($paddingRight: 0, $thumbColor, $backgroundColor) {
34
+ @include custom-scroll($thumbColor, $backgroundColor);
35
+ padding-right: $paddingRight;
36
+ overflow: auto;
37
+ }