@seamly/web-ui 24.5.0 → 25.1.0-beta.1

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 (154) hide show
  1. package/build/dist/lib/index.debug.js +2129 -1810
  2. package/build/dist/lib/index.debug.js.map +1 -1
  3. package/build/dist/lib/index.debug.min.js +1 -1
  4. package/build/dist/lib/index.debug.min.js.LICENSE.txt +49 -7
  5. package/build/dist/lib/index.debug.min.js.map +1 -1
  6. package/build/dist/lib/index.js +732 -398
  7. package/build/dist/lib/index.js.map +1 -1
  8. package/build/dist/lib/index.min.js +1 -1
  9. package/build/dist/lib/index.min.js.LICENSE.txt +16 -1
  10. package/build/dist/lib/index.min.js.map +1 -1
  11. package/build/dist/lib/style-guide.js +305 -93
  12. package/build/dist/lib/style-guide.js.map +1 -1
  13. package/build/dist/lib/style-guide.min.js +1 -1
  14. package/build/dist/lib/style-guide.min.js.map +1 -1
  15. package/build/dist/lib/styles-default-implementation.css +1 -1
  16. package/build/dist/lib/styles.css +1 -1
  17. package/package.json +27 -38
  18. package/src/javascripts/core/api/api.types.ts +3 -0
  19. package/src/javascripts/core/api/asyncapi.types.ts +292 -69
  20. package/src/javascripts/core/api/channel.types.ts +301 -69
  21. package/src/javascripts/core/api/conversation-connector.ts +1 -3
  22. package/src/javascripts/core/api/errors/seamly-api-error.ts +0 -1
  23. package/src/javascripts/core/api/errors/seamly-base-error.ts +1 -1
  24. package/src/javascripts/core/api/index.ts +7 -7
  25. package/src/javascripts/core/api/utils.ts +0 -1
  26. package/src/javascripts/core/domains/app/actions.ts +1 -1
  27. package/src/javascripts/core/domains/app/hooks.ts +1 -1
  28. package/src/javascripts/core/domains/config/hooks.ts +1 -1
  29. package/src/javascripts/core/domains/config/selectors.ts +1 -1
  30. package/src/javascripts/core/domains/config/slice.ts +2 -2
  31. package/src/javascripts/core/domains/forms/context.ts +1 -1
  32. package/src/javascripts/core/domains/forms/hooks.ts +12 -12
  33. package/src/javascripts/core/domains/forms/provider.tsx +9 -9
  34. package/src/javascripts/core/domains/i18n/actions.ts +1 -1
  35. package/src/javascripts/core/domains/i18n/hooks.ts +3 -3
  36. package/src/javascripts/core/domains/interrupt/hooks.ts +1 -1
  37. package/src/javascripts/core/domains/store/index.ts +2 -2
  38. package/src/javascripts/core/domains/store/slice.ts +47 -34
  39. package/src/javascripts/core/domains/store/store.types.ts +3 -7
  40. package/src/javascripts/core/domains/translations/components/options-button.tsx +2 -2
  41. package/src/javascripts/core/domains/translations/components/options-dialog/index.tsx +1 -1
  42. package/src/javascripts/core/domains/translations/components/options-dialog/translation-option.tsx +1 -1
  43. package/src/javascripts/core/domains/translations/components/options-dialog/translation-options.tsx +2 -2
  44. package/src/javascripts/core/domains/translations/components/translation-status.tsx +1 -1
  45. package/src/javascripts/core/domains/translations/hooks.ts +2 -2
  46. package/src/javascripts/core/domains/translations/middleware.ts +4 -2
  47. package/src/javascripts/core/domains/visibility/actions.ts +2 -2
  48. package/src/javascripts/core/domains/visibility/hooks.ts +5 -5
  49. package/src/javascripts/core/lib/debug.ts +1 -1
  50. package/src/javascripts/core/lib/engine/index.tsx +5 -5
  51. package/src/javascripts/core/lib/external-api/index.ts +6 -6
  52. package/src/javascripts/core/lib/mutex.ts +0 -1
  53. package/src/javascripts/core/lib/split-url-params.ts +1 -1
  54. package/src/javascripts/core/lib/store/index.ts +0 -1
  55. package/src/javascripts/core/lib/store/providers/app-storage.js +4 -7
  56. package/src/javascripts/core/lib/store/providers/app-storage.ts +4 -6
  57. package/src/javascripts/core/ui/components/app-options/index.tsx +1 -1
  58. package/src/javascripts/core/ui/components/chat-status/index.tsx +1 -1
  59. package/src/javascripts/core/ui/components/conversation/component-filter.tsx +1 -3
  60. package/src/javascripts/core/ui/components/conversation/conversation.tsx +9 -11
  61. package/src/javascripts/core/ui/components/conversation/event/card-component.tsx +3 -3
  62. package/src/javascripts/core/ui/components/conversation/event/carousel-component/components/pagination.tsx +1 -1
  63. package/src/javascripts/core/ui/components/conversation/event/carousel-component/index.tsx +1 -1
  64. package/src/javascripts/core/ui/components/conversation/event/chat-scroll/chat-scroll-provider.tsx +1 -1
  65. package/src/javascripts/core/ui/components/conversation/event/choice-prompt.tsx +5 -5
  66. package/src/javascripts/core/ui/components/conversation/event/conversation-suggestions.tsx +1 -1
  67. package/src/javascripts/core/ui/components/conversation/event/divider/variants/new-translation.tsx +3 -3
  68. package/src/javascripts/core/ui/components/conversation/event/divider/variants/time-indicator.tsx +1 -1
  69. package/src/javascripts/core/ui/components/conversation/event/event-participant.tsx +1 -1
  70. package/src/javascripts/core/ui/components/conversation/event/event.tsx +1 -1
  71. package/src/javascripts/core/ui/components/conversation/event/image-lightbox.tsx +1 -1
  72. package/src/javascripts/core/ui/components/conversation/event/image.tsx +2 -2
  73. package/src/javascripts/core/ui/components/conversation/event/participant.tsx +1 -1
  74. package/src/javascripts/core/ui/components/conversation/event/splash.tsx +0 -1
  75. package/src/javascripts/core/ui/components/conversation/event/text.tsx +2 -2
  76. package/src/javascripts/core/ui/components/conversation/event/upload.tsx +3 -3
  77. package/src/javascripts/core/ui/components/conversation/event/video.tsx +2 -2
  78. package/src/javascripts/core/ui/components/conversation/event-divider.tsx +1 -1
  79. package/src/javascripts/core/ui/components/conversation/message-container.tsx +2 -4
  80. package/src/javascripts/core/ui/components/conversation/use-chat-scroll.ts +3 -3
  81. package/src/javascripts/core/ui/components/core/seamly-activity-monitor.tsx +1 -1
  82. package/src/javascripts/core/ui/components/core/seamly-api-context.ts +1 -1
  83. package/src/javascripts/core/ui/components/core/seamly-core.tsx +3 -3
  84. package/src/javascripts/core/ui/components/core/seamly-event-subscriber.ts +9 -7
  85. package/src/javascripts/core/ui/components/core/seamly-file-upload.tsx +2 -3
  86. package/src/javascripts/core/ui/components/core/seamly-initializer.tsx +1 -1
  87. package/src/javascripts/core/ui/components/core/seamly-instance-functions-loader.ts +3 -3
  88. package/src/javascripts/core/ui/components/core/seamly-live-region.tsx +1 -1
  89. package/src/javascripts/core/ui/components/core/seamly-new-notifications.ts +1 -1
  90. package/src/javascripts/core/ui/components/core/seamly-read-state.ts +1 -1
  91. package/src/javascripts/core/ui/components/entry/entry-container.tsx +8 -3
  92. package/src/javascripts/core/ui/components/entry/text-entry/hooks.ts +21 -14
  93. package/src/javascripts/core/ui/components/entry/text-entry/index.tsx +1 -1
  94. package/src/javascripts/core/ui/components/entry/text-entry/text-entry-form.tsx +1 -1
  95. package/src/javascripts/core/ui/components/entry/upload/file-upload-form.tsx +1 -1
  96. package/src/javascripts/core/ui/components/entry/upload/index.tsx +1 -1
  97. package/src/javascripts/core/ui/components/entry/upload-toggle.tsx +2 -1
  98. package/src/javascripts/core/ui/components/form-controls/error.tsx +1 -1
  99. package/src/javascripts/core/ui/components/form-controls/file-input.tsx +1 -1
  100. package/src/javascripts/core/ui/components/form-controls/input.tsx +1 -1
  101. package/src/javascripts/core/ui/components/form-controls/wrapper.tsx +1 -1
  102. package/src/javascripts/core/ui/components/layout/agent-info.tsx +1 -1
  103. package/src/javascripts/core/ui/components/layout/chat-frame.tsx +1 -1
  104. package/src/javascripts/core/ui/components/layout/chat.tsx +8 -6
  105. package/src/javascripts/core/ui/components/layout/continue-chat-messages.tsx +1 -1
  106. package/src/javascripts/core/ui/components/layout/header.tsx +1 -1
  107. package/src/javascripts/core/ui/components/layout/interrupt.tsx +1 -1
  108. package/src/javascripts/core/ui/components/layout/pre-chat-messages.tsx +1 -1
  109. package/src/javascripts/core/ui/components/options/options-button.tsx +1 -3
  110. package/src/javascripts/core/ui/components/options/options-frame.tsx +1 -1
  111. package/src/javascripts/core/ui/components/options/transcript/index.tsx +1 -1
  112. package/src/javascripts/core/ui/components/suggestions/index.tsx +2 -2
  113. package/src/javascripts/core/ui/components/suggestions/suggestions-list.tsx +1 -1
  114. package/src/javascripts/core/ui/components/view/index.tsx +3 -3
  115. package/src/javascripts/core/ui/components/view/window-view/collapse-button.tsx +10 -1
  116. package/src/javascripts/core/ui/components/view/window-view/window-open-button.tsx +9 -3
  117. package/src/javascripts/core/ui/components/widgets/in-out-transition.tsx +2 -2
  118. package/src/javascripts/core/ui/components/widgets/lightbox.tsx +1 -1
  119. package/src/javascripts/core/ui/hooks/file-upload-hooks.ts +1 -1
  120. package/src/javascripts/core/ui/hooks/focus-helper-hooks.ts +6 -1
  121. package/src/javascripts/core/ui/hooks/seamly-entry-hooks.ts +1 -1
  122. package/src/javascripts/core/ui/hooks/seamly-option-hooks.ts +1 -1
  123. package/src/javascripts/core/ui/hooks/seamly-state-hooks.ts +9 -4
  124. package/src/javascripts/core/ui/hooks/use-debounce.ts +1 -1
  125. package/src/javascripts/core/ui/hooks/use-interval.ts +0 -1
  126. package/src/javascripts/core/ui/hooks/use-notifications.ts +2 -3
  127. package/src/javascripts/core/ui/hooks/use-seamly-chat.ts +2 -2
  128. package/src/javascripts/core/ui/hooks/use-seamly-commands.ts +2 -2
  129. package/src/javascripts/core/ui/hooks/use-seamly-conversation.ts +1 -1
  130. package/src/javascripts/core/ui/hooks/use-seamly-idle-detach-countdown.ts +15 -10
  131. package/src/javascripts/core/ui/hooks/use-session-expired-command.ts +1 -1
  132. package/src/javascripts/core/ui/hooks/use-single-file-upload.ts +1 -1
  133. package/src/javascripts/core/ui/hooks/utility-hooks.ts +1 -2
  134. package/src/javascripts/core/ui/utils/seamly-utils.ts +0 -2
  135. package/src/javascripts/core/ui/utils/validations.ts +1 -2
  136. package/src/javascripts/style-guide/components/app.tsx +2 -2
  137. package/src/javascripts/style-guide/components/static-core.tsx +2 -2
  138. package/src/javascripts/style-guide/components/view.tsx +1 -1
  139. package/src/javascripts/style-guide/state-helpers/index.ts +0 -2
  140. package/src/javascripts/style-guide/states.ts +5 -42
  141. package/src/javascripts/style-guide/style-guide-engine.tsx +1 -1
  142. package/src/stylesheets/5-components/_message-body.scss +0 -10
  143. package/src/stylesheets/6-default-implementation/_hover.scss +0 -7
  144. package/src/stylesheets/styles.scss +0 -1
  145. package/webpack/config.common.js +4 -11
  146. package/webpack/config.dev.js +0 -1
  147. package/webpack/config.package.js +5 -7
  148. package/webpack/config.site.js +2 -4
  149. package/webpack/config.test.js +1 -2
  150. package/webpack/defaults.js +0 -1
  151. package/webpack/parts/babel-loader-browser-plugins.js +0 -1
  152. package/webpack/parts/dev-server.js +0 -1
  153. package/src/javascripts/core/ui/components/conversation/event/cta.tsx +0 -54
  154. package/src/stylesheets/5-components/_message-cta.scss +0 -17
@@ -1,10 +1,10 @@
1
- import { useEffect, useMemo } from 'preact/hooks'
2
1
  import { maxCharacterSrDebounceDelay, maxCharacterWarningLimit } from 'config'
3
2
  import { useConfig } from 'domains/config/hooks'
4
3
  import { useFormControl } from 'domains/forms/hooks'
5
4
  import { useI18n } from 'domains/i18n/hooks'
6
5
  import { useAppDispatch } from 'domains/store'
7
6
  import { clearAbortTransaction } from 'domains/store/slice'
7
+ import { useEffect, useMemo } from 'preact/hooks'
8
8
  import { useLiveRegion } from 'ui/hooks/live-region-hooks'
9
9
  import {
10
10
  useEntryTextLimit,
@@ -60,9 +60,20 @@ export const useEntryTextTranslation = (controlName: 'textMessageEntry') => {
60
60
  const { hasCharacterLimit, characterLimit } = useCharacterLimit(controlName)
61
61
 
62
62
  const {
63
- entryMeta: { optionsOverride },
63
+ entryMeta: { active: entryType, optionsOverride },
64
64
  } = useSeamlyStateContext()
65
65
 
66
+ let labelOverride: string | null = null
67
+ let placeholderOverride: string | null = null
68
+ if (
69
+ entryType &&
70
+ optionsOverride &&
71
+ typeof optionsOverride[entryType] === 'object'
72
+ ) {
73
+ labelOverride = optionsOverride[entryType].label
74
+ placeholderOverride = optionsOverride[entryType].placeholder
75
+ }
76
+
66
77
  const { alwaysShowEntryLabel } = useConfig()
67
78
  const { t } = useI18n()
68
79
 
@@ -70,32 +81,28 @@ export const useEntryTextTranslation = (controlName: 'textMessageEntry') => {
70
81
  () =>
71
82
  t('input.inputPlaceholder', {
72
83
  hasLimit: hasCharacterLimit,
73
- text:
74
- optionsOverride?.text?.placeholder || t('input.inputPlaceholderText'),
84
+ text: placeholderOverride || t('input.inputPlaceholderText'),
75
85
  limit: hasCharacterLimit ? characterLimit : null,
76
86
  }),
77
- [t, hasCharacterLimit, characterLimit, optionsOverride?.text?.placeholder],
87
+ [t, hasCharacterLimit, characterLimit, placeholderOverride],
78
88
  )
79
89
 
80
90
  const label: string = useMemo(
81
91
  () =>
82
92
  t('input.inputLabel', {
83
- hasLimit: !optionsOverride?.text?.label ? hasCharacterLimit : false,
84
- text: optionsOverride?.text?.label || t('input.inputLabelText'),
85
- limit:
86
- !optionsOverride?.text?.label && hasCharacterLimit
87
- ? characterLimit
88
- : null,
93
+ hasLimit: !labelOverride ? hasCharacterLimit : false,
94
+ text: labelOverride || t('input.inputLabelText'),
95
+ limit: !labelOverride && hasCharacterLimit ? characterLimit : null,
89
96
  }),
90
- [t, hasCharacterLimit, characterLimit, optionsOverride?.text?.label],
97
+ [t, hasCharacterLimit, characterLimit, labelOverride],
91
98
  )
92
99
 
93
100
  const labelClass = useMemo(
94
101
  () =>
95
- alwaysShowEntryLabel === true || optionsOverride?.text?.label
102
+ alwaysShowEntryLabel === true || labelOverride
96
103
  ? 'label'
97
104
  : 'visually-hidden',
98
- [alwaysShowEntryLabel, optionsOverride?.text?.label],
105
+ [alwaysShowEntryLabel, labelOverride],
99
106
  )
100
107
 
101
108
  return { placeholder, label, labelClass }
@@ -1,7 +1,7 @@
1
- import { useCallback } from 'preact/hooks'
2
1
  import FormProvider from 'domains/forms/provider'
3
2
  import { visibilityStates } from 'domains/visibility/constants'
4
3
  import { useVisibility } from 'domains/visibility/hooks'
4
+ import { useCallback } from 'preact/hooks'
5
5
  import {
6
6
  useSeamlyCommands,
7
7
  useSkiplink,
@@ -1,8 +1,8 @@
1
- import { useCallback, useLayoutEffect } from 'preact/hooks'
2
1
  import { useFormControl } from 'domains/forms/hooks'
3
2
  import { useI18n } from 'domains/i18n/hooks'
4
3
  import { useVisibility } from 'domains/visibility/hooks'
5
4
  import { className } from 'lib/css'
5
+ import { useCallback, useLayoutEffect } from 'preact/hooks'
6
6
  import Form from 'ui/components/form-controls/form'
7
7
  import Input from 'ui/components/form-controls/input'
8
8
  import Icon from 'ui/components/layout/icon'
@@ -1,8 +1,8 @@
1
- import { FC } from 'preact/compat'
2
1
  import { FormControlName } from 'domains/forms/forms.types'
3
2
  import { useFormControl } from 'domains/forms/hooks'
4
3
  import { useI18n } from 'domains/i18n/hooks'
5
4
  import { className } from 'lib/css'
5
+ import { FC } from 'preact/compat'
6
6
  import FileInput from 'ui/components/form-controls/file-input'
7
7
  import Form from 'ui/components/form-controls/form'
8
8
 
@@ -1,7 +1,7 @@
1
- import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
2
1
  import FormProvider from 'domains/forms/provider'
3
2
  import { useI18n } from 'domains/i18n/hooks'
4
3
  import { className } from 'lib/css'
4
+ import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
5
5
  import UploadProgress from 'ui/components/widgets/upload-progress'
6
6
  import { useSeamlyEntry } from 'ui/hooks/seamly-entry-hooks'
7
7
  import {
@@ -1,6 +1,6 @@
1
- import { useEffect, useRef, useState } from 'preact/hooks'
2
1
  import { useI18n } from 'domains/i18n/hooks'
3
2
  import { className } from 'lib/css'
3
+ import { useEffect, useRef, useState } from 'preact/hooks'
4
4
  import Icon from 'ui/components/layout/icon'
5
5
  import InOutTransition, {
6
6
  transitionStartStates,
@@ -80,6 +80,7 @@ const UploadToggle = () => {
80
80
  aria-disabled={!showUploadButton}
81
81
  type="button"
82
82
  onClick={showUploadButton ? onClickHandler : undefined}
83
+ tabIndex={!showUploadButton ? -1 : undefined}
83
84
  >
84
85
  <Icon
85
86
  name="file"
@@ -1,5 +1,5 @@
1
- import { useEffect, useState } from 'preact/hooks'
2
1
  import { className } from 'lib/css'
2
+ import { useEffect, useState } from 'preact/hooks'
3
3
  import Icon from 'ui/components/layout/icon'
4
4
 
5
5
  export default function Error({ id, error }) {
@@ -1,6 +1,6 @@
1
- import { useCallback, useState } from 'preact/hooks'
2
1
  import { useFormContext, useFormControl } from 'domains/forms/hooks'
3
2
  import { className } from 'lib/css'
3
+ import { useCallback, useState } from 'preact/hooks'
4
4
  import Icon from 'ui/components/layout/icon'
5
5
  import { useGeneratedId } from 'ui/hooks/seamly-hooks'
6
6
  import Error from './error'
@@ -1,6 +1,6 @@
1
+ import { useFormContext, useFormControl } from 'domains/forms/hooks'
1
2
  import { InputHTMLAttributes } from 'preact/compat'
2
3
  import { useRef, useLayoutEffect } from 'preact/hooks'
3
- import { useFormContext, useFormControl } from 'domains/forms/hooks'
4
4
  import FormControlWrapper from './wrapper'
5
5
 
6
6
  type InputProps = InputHTMLAttributes<HTMLInputElement> & {
@@ -1,5 +1,5 @@
1
- import { FC, HTMLAttributes } from 'preact/compat'
2
1
  import { className } from 'lib/css'
2
+ import { FC, HTMLAttributes } from 'preact/compat'
3
3
  import Error from './error'
4
4
 
5
5
  type FormControlWrapperProps = {
@@ -1,9 +1,9 @@
1
- import { useSelector } from 'react-redux'
2
1
  import { useStartChatIcon } from 'domains/config/hooks'
3
2
  import { useI18n } from 'domains/i18n/hooks'
4
3
  import { selectHasError } from 'domains/interrupt/selectors'
5
4
  import { useVisibility } from 'domains/visibility/hooks'
6
5
  import { className } from 'lib/css'
6
+ import { useSelector } from 'react-redux'
7
7
  import {
8
8
  useSeamlyCurrentAgent,
9
9
  useSeamlyHeaderData,
@@ -1,8 +1,8 @@
1
- import { useSelector } from 'react-redux'
2
1
  import { selectHasError } from 'domains/interrupt/selectors'
3
2
  import TranslationStatus from 'domains/translations/components/translation-status'
4
3
  import { useVisibility } from 'domains/visibility/hooks'
5
4
  import { className } from 'lib/css'
5
+ import { useSelector } from 'react-redux'
6
6
  import AppOptions from 'ui/components/app-options'
7
7
  import ChatScrollProvider from 'ui/components/conversation/event/chat-scroll/chat-scroll-provider'
8
8
  import EntryContainer from 'ui/components/entry/entry-container'
@@ -1,13 +1,13 @@
1
- import { ComponentChildren } from 'preact'
2
- import { forwardRef } from 'preact/compat'
3
1
  import { useUserHasResponded } from 'domains/app/hooks'
4
2
  import { useConfig } from 'domains/config/hooks'
5
3
  import { useI18n } from 'domains/i18n/hooks'
6
- import { visibilityStates } from 'domains/visibility/constants'
7
4
  import { useVisibility } from 'domains/visibility/hooks'
8
5
  import { className } from 'lib/css'
6
+ import { ComponentChildren } from 'preact'
7
+ import { forwardRef } from 'preact/compat'
9
8
  import Suggestions from 'ui/components/suggestions'
10
9
  import { useSeamlyAppContainerClassNames } from 'ui/hooks/component-helper-hooks'
10
+ import { useWindowOpenButtonFocusing } from 'ui/hooks/focus-helper-hooks'
11
11
  import { useSeamlyLayoutMode } from 'ui/hooks/seamly-state-hooks'
12
12
  import { useGeneratedId } from 'ui/hooks/utility-hooks'
13
13
 
@@ -15,7 +15,8 @@ const Chat = forwardRef<
15
15
  HTMLElement,
16
16
  { children: ComponentChildren; className?: string }
17
17
  >(({ children, className: givenClassName = '' }, forwardedRef) => {
18
- const { isOpen, isVisible, setVisibility } = useVisibility()
18
+ const { closeChat, isOpen, isVisible } = useVisibility()
19
+ const focusWindowOpenButton = useWindowOpenButtonFocusing()
19
20
  const { namespace, layoutMode } = useConfig()
20
21
  const { isInline } = useSeamlyLayoutMode()
21
22
  const appContainerClassNames = useSeamlyAppContainerClassNames()
@@ -46,7 +47,8 @@ const Chat = forwardRef<
46
47
  const onKeyDownHandler = (e) => {
47
48
  if ((e.code && e.code === 'Escape') || e.keyCode === 27)
48
49
  if (!isInline && isOpen) {
49
- setVisibility({ visibility: visibilityStates.minimized })
50
+ closeChat()
51
+ focusWindowOpenButton()
50
52
  }
51
53
  }
52
54
 
@@ -64,7 +66,7 @@ const Chat = forwardRef<
64
66
  className={className('chat__title', 'visually-hidden')}
65
67
  id={headingId}
66
68
  >
67
- {t('chat.srLabel')}
69
+ {t('window.srModalLayoutLabel')}
68
70
  </h2>
69
71
  <div className={className('chat-wrapper')}>{children}</div>
70
72
  {layoutMode === 'inline' && isOpen && <Suggestions isAside={true} />}
@@ -1,6 +1,6 @@
1
- import { useMemo } from 'preact/hooks'
2
1
  import { useI18n } from 'domains/i18n/hooks'
3
2
  import { ChannelEvent } from 'domains/store/store.types'
3
+ import { useMemo } from 'preact/hooks'
4
4
  import { CollapsedChatMessages } from './collapsed-chat-messages'
5
5
 
6
6
  export default function ContinueChatMessages() {
@@ -1,6 +1,6 @@
1
- import { useRef } from 'preact/hooks'
2
1
  import { useI18n } from 'domains/i18n/hooks'
3
2
  import { className } from 'lib/css'
3
+ import { useRef } from 'preact/hooks'
4
4
  import { useSeamlyStateContext } from 'ui/hooks/seamly-hooks'
5
5
  import Icon from './icon'
6
6
 
@@ -1,6 +1,6 @@
1
- import { useEffect } from 'preact/hooks'
2
1
  import { useInterrupt } from 'domains/interrupt/hooks'
3
2
  import { className } from 'lib/css'
3
+ import { useEffect } from 'preact/hooks'
4
4
  import CollapseButton from 'ui/components/view/window-view/collapse-button'
5
5
  import {
6
6
  useGeneratedId,
@@ -1,7 +1,7 @@
1
- import { useSelector } from 'react-redux'
2
1
  import { useConfig } from 'domains/config/hooks'
3
2
  import { selectHasError } from 'domains/interrupt/selectors'
4
3
  import { useVisibility } from 'domains/visibility/hooks'
4
+ import { useSelector } from 'react-redux'
5
5
  import { CollapsedChatMessages } from './collapsed-chat-messages'
6
6
 
7
7
  export default function PreChatMessages() {
@@ -1,6 +1,6 @@
1
- import { useEffect, useMemo, useRef, useState } from 'preact/hooks'
2
1
  import { useI18n } from 'domains/i18n/hooks'
3
2
  import { className } from 'lib/css'
3
+ import { useEffect, useMemo, useRef, useState } from 'preact/hooks'
4
4
  import Icon from 'ui/components/layout/icon'
5
5
  import InOutTransition, {
6
6
  transitionStartStates,
@@ -167,9 +167,7 @@ const OptionsButton = () => {
167
167
  <div
168
168
  className={className('options__container')}
169
169
  onKeyDown={onMainKeyDownHandler}
170
- // eslint-disable-next-line react/no-unknown-property
171
170
  onFocusOut={onFocusOutHandler}
172
- // eslint-disable-next-line react/no-unknown-property
173
171
  onFocusIn={onFocusInHandler}
174
172
  >
175
173
  <InOutTransition
@@ -1,6 +1,6 @@
1
+ import { className } from 'lib/css'
1
2
  import { FC } from 'preact/compat'
2
3
  import { MutableRef, useCallback, useEffect } from 'preact/hooks'
3
- import { className } from 'lib/css'
4
4
  import Icon from 'ui/components/layout/icon'
5
5
  import {
6
6
  useGeneratedId,
@@ -1,6 +1,6 @@
1
- import { useCallback, useMemo, useState } from 'preact/hooks'
2
1
  import FormProvider from 'domains/forms/provider'
3
2
  import { useI18n } from 'domains/i18n/hooks'
3
+ import { useCallback, useMemo, useState } from 'preact/hooks'
4
4
  import OptionsFrame from 'ui/components/options/options-frame'
5
5
  import {
6
6
  useGeneratedId,
@@ -1,5 +1,3 @@
1
- import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
2
- import { useSelector } from 'react-redux'
3
1
  import { useUserHasResponded } from 'domains/app/hooks'
4
2
  import { useConfig } from 'domains/config/hooks'
5
3
  import { useI18n } from 'domains/i18n/hooks'
@@ -10,6 +8,8 @@ import { visibilityStates } from 'domains/visibility/constants'
10
8
  import { useVisibility } from 'domains/visibility/hooks'
11
9
  import { className } from 'lib/css'
12
10
  import { randomId } from 'lib/id'
11
+ import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
12
+ import { useSelector } from 'react-redux'
13
13
  import SuggestionsList from 'ui/components/suggestions/suggestions-list'
14
14
  import InOutTransition, {
15
15
  transitionStartStates,
@@ -1,5 +1,5 @@
1
- import { FC } from 'preact/compat'
2
1
  import { ServiceDataEvent } from 'domains/store/store.types'
2
+ import { FC } from 'preact/compat'
3
3
  import { className } from '../../../lib/css'
4
4
  import SuggestionsItem from './suggestions-item'
5
5
 
@@ -1,6 +1,3 @@
1
- import { RefCallback } from 'preact'
2
- import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
3
- import { useSelector } from 'react-redux'
4
1
  import { useUserHasResponded } from 'domains/app/hooks'
5
2
  import { useConfig } from 'domains/config/hooks'
6
3
  import { useI18n } from 'domains/i18n/hooks'
@@ -8,6 +5,9 @@ import { selectLastUnreadEvent } from 'domains/store/selectors'
8
5
  import { useTranslatedEventData } from 'domains/translations/hooks'
9
6
  import { useVisibility } from 'domains/visibility/hooks'
10
7
  import { className } from 'lib/css'
8
+ import { RefCallback } from 'preact'
9
+ import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
10
+ import { useSelector } from 'react-redux'
11
11
  import AppView from 'ui/components/view/app-view'
12
12
  import InlineView from 'ui/components/view/inline-view'
13
13
  import WindowView from 'ui/components/view/window-view'
@@ -1,18 +1,27 @@
1
1
  import { useI18n } from 'domains/i18n/hooks'
2
2
  import { useVisibility } from 'domains/visibility/hooks'
3
3
  import { className } from 'lib/css'
4
+ import { useCallback } from 'preact/hooks'
4
5
  import Icon from 'ui/components/layout/icon'
6
+ import { useWindowOpenButtonFocusing } from 'ui/hooks/focus-helper-hooks'
5
7
  import { useSeamlyLayoutMode } from 'ui/hooks/seamly-state-hooks'
6
8
 
7
9
  const CollapseButton = () => {
8
10
  const { t } = useI18n()
9
11
  const { isOpen, closeChat } = useVisibility()
10
12
  const { isWindow } = useSeamlyLayoutMode()
13
+ const focusWindowOpenButton = useWindowOpenButtonFocusing()
14
+
15
+ const handleClick = useCallback(() => {
16
+ closeChat()
17
+ focusWindowOpenButton()
18
+ }, [closeChat, focusWindowOpenButton])
19
+
11
20
  return isOpen && isWindow ? (
12
21
  <button
13
22
  type="button"
14
23
  className={className('button', 'collapse-button')}
15
- onClick={closeChat}
24
+ onClick={handleClick}
16
25
  >
17
26
  <Icon name="chevronDown" size="32" alt={t('window.srCollapseButton')} />
18
27
  </button>
@@ -1,16 +1,17 @@
1
- import { useCallback } from 'preact/hooks'
2
- import { useSelector } from 'react-redux'
3
1
  import { useStartChatIcon } from 'domains/config/hooks'
4
2
  import { useI18n } from 'domains/i18n/hooks'
5
3
  import { selectHasError } from 'domains/interrupt/selectors'
6
4
  import { useVisibility } from 'domains/visibility/hooks'
7
5
  import { className } from 'lib/css'
6
+ import { useCallback } from 'preact/hooks'
7
+ import { useSelector } from 'react-redux'
8
8
  import Icon from 'ui/components/layout/icon'
9
9
  import InOutTransition, {
10
10
  transitionStartStates,
11
11
  } from 'ui/components/widgets/in-out-transition'
12
12
  import { useSkiplinkTargetFocusing } from 'ui/hooks/focus-helper-hooks'
13
13
  import { useSeamlyHasConversation } from 'ui/hooks/seamly-api-hooks'
14
+ import { useSeamlyStateContext } from 'ui/hooks/seamly-hooks'
14
15
  import {
15
16
  useSeamlyCurrentAgent,
16
17
  useSeamlyUnreadCount,
@@ -41,21 +42,26 @@ const WindowOpenButton = ({ onClick }) => {
41
42
  : t('window.openButton.srStart')
42
43
  const focusSkiplinkTarget = useSkiplinkTargetFocusing()
43
44
  const { isOpen } = useVisibility()
45
+ const { windowOpenButtonId } = useSeamlyStateContext()
44
46
  const count = useSeamlyUnreadCount()
47
+
45
48
  const handleClick = useCallback(() => {
46
49
  onClick()
47
50
  focusSkiplinkTarget()
48
51
  }, [focusSkiplinkTarget, onClick])
52
+
49
53
  return (
50
54
  <InOutTransition
51
55
  isActive={!isOpen}
52
56
  transitionStartState={transitionStartStates.rendered}
53
57
  >
54
58
  <button
59
+ type="button"
55
60
  className={className('window-open-button')}
56
61
  aria-label={ariaLabel}
57
- aria-hidden={isOpen}
58
62
  onClick={handleClick}
63
+ inert={isOpen || undefined}
64
+ id={windowOpenButtonId}
59
65
  >
60
66
  <InOutTransition
61
67
  isActive={!!count}
@@ -1,8 +1,8 @@
1
+ import { defaultTransitionTimeMs } from 'config'
2
+ import { className } from 'lib/css'
1
3
  import { cloneElement, toChildArray } from 'preact'
2
4
  import { FC } from 'preact/compat'
3
5
  import { useEffect, useMemo, useRef, useState } from 'preact/hooks'
4
- import { defaultTransitionTimeMs } from 'config'
5
- import { className } from 'lib/css'
6
6
  import useTimeout from 'ui/hooks/use-timeout'
7
7
  import { ValueOf, childIsVNode } from 'ui/utils/general-utils'
8
8
 
@@ -1,7 +1,7 @@
1
- import { useRef } from 'preact/hooks'
2
1
  import { useConfig } from 'domains/config/hooks'
3
2
  import { useI18n } from 'domains/i18n/hooks'
4
3
  import { className } from 'lib/css'
4
+ import { useRef } from 'preact/hooks'
5
5
  import Icon from 'ui/components/layout/icon'
6
6
  import {
7
7
  useSeamlyActivityEventHandler,
@@ -1,6 +1,6 @@
1
- import { useCallback, useContext } from 'preact/hooks'
2
1
  import { useAppDispatch } from 'domains/store'
3
2
  import { clearAllUploads } from 'domains/store/slice'
3
+ import { useCallback, useContext } from 'preact/hooks'
4
4
  import SeamlyFileUploadContext from 'ui/components/core/seamly-file-upload-context'
5
5
  import { useSeamlyStateContext } from './seamly-state-hooks'
6
6
 
@@ -1,6 +1,6 @@
1
- import { useCallback, useRef } from 'preact/hooks'
2
1
  import { useAppDispatch } from 'domains/store'
3
2
  import { setSeamlyContainerElement } from 'domains/store/slice'
3
+ import { useCallback, useRef } from 'preact/hooks'
4
4
  import {
5
5
  focusElement,
6
6
  runIfElementContainsOrHasFocus,
@@ -45,6 +45,11 @@ export const useSkiplinkTargetFocusing = () => {
45
45
  return useElementFocusingById(skiplinkTargetId)
46
46
  }
47
47
 
48
+ export const useWindowOpenButtonFocusing = () => {
49
+ const { windowOpenButtonId } = useSeamlyStateContext()
50
+ return useElementFocusingById(windowOpenButtonId)
51
+ }
52
+
48
53
  export const useFocusIfSeamlyContainedFocus = () => {
49
54
  const containerElementRef = useRef<
50
55
  HTMLElement | ((_element: any) => void) | null
@@ -1,4 +1,3 @@
1
- import { useCallback, useEffect, useRef } from 'preact/hooks'
2
1
  import { typingTimeout } from 'config'
3
2
  import { useAppDispatch } from 'domains/store'
4
3
  import {
@@ -6,6 +5,7 @@ import {
6
5
  setBlockAutoEntrySwitch,
7
6
  setUserEntryType,
8
7
  } from 'domains/store/slice'
8
+ import { useCallback, useEffect, useRef } from 'preact/hooks'
9
9
  import { useSeamlyCommands, useSeamlyOptions } from 'ui/hooks/seamly-hooks'
10
10
  import { useSeamlyStateContext } from 'ui/hooks/seamly-state-hooks'
11
11
  import { actionTypes } from 'ui/utils/seamly-utils'
@@ -1,4 +1,3 @@
1
- import { useCallback } from 'preact/hooks'
2
1
  import { useI18n } from 'domains/i18n/hooks'
3
2
  import { useAppDispatch } from 'domains/store'
4
3
  import {
@@ -7,6 +6,7 @@ import {
7
6
  setUserSelectedOption as dispatchUserSelectedOption,
8
7
  setUserSelectedOptions as dispatchUserSelectedOptions,
9
8
  } from 'domains/store/slice'
9
+ import { useCallback } from 'preact/hooks'
10
10
  import { useElementFocusingById } from 'ui/hooks/focus-helper-hooks'
11
11
  import { useSeamlyObjectStore } from 'ui/hooks/seamly-api-hooks'
12
12
  import { useSeamlyStateContext } from 'ui/hooks/seamly-state-hooks'
@@ -1,11 +1,11 @@
1
1
  import { createSelector } from '@reduxjs/toolkit'
2
- import { useSelector } from 'react-redux'
3
2
  import { selectUserHasResponded } from 'domains/app/selectors'
4
3
  import { useConfig } from 'domains/config/hooks'
5
4
  import * as ConfigSelectors from 'domains/config/selectors'
6
- import { microsecondsToMilliseconds } from 'ui/utils/general-utils'
7
5
  import type { RootState } from 'domains/store'
8
6
  import type { ChannelEvent, ServiceDataEvent } from 'domains/store/store.types'
7
+ import { useSelector } from 'react-redux'
8
+ import { microsecondsToMilliseconds } from 'ui/utils/general-utils'
9
9
 
10
10
  export const selectState = ({ state }: RootState) => state
11
11
  export const useSeamlyStateContext = () => useSelector(selectState)
@@ -131,10 +131,15 @@ export const useSeamlyServiceData = (key: string) => {
131
131
 
132
132
  export const useEntryTextLimit = () => {
133
133
  const {
134
- entryMeta: { options, optionsOverride },
134
+ entryMeta: { active: entryType, options, optionsOverride },
135
135
  } = useSeamlyStateContext()
136
136
 
137
- const { limit } = optionsOverride?.text || options?.text || { limit: null }
137
+ let limit: number | null = null
138
+ if (entryType && typeof optionsOverride[entryType]?.limit === 'number') {
139
+ limit = optionsOverride[entryType].limit
140
+ } else if (entryType && typeof options[entryType]?.limit === 'number') {
141
+ limit = options[entryType].limit
142
+ }
138
143
 
139
144
  return {
140
145
  hasLimit: limit !== null,
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useRef, useState } from 'preact/hooks'
2
2
 
3
- const useDebounce = <T extends unknown>(value: T, delay = 20): T => {
3
+ const useDebounce = <T>(value: T, delay = 20): T => {
4
4
  const [debouncedValue, setDebouncedValue] = useState<T>(value)
5
5
  const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
6
6
 
@@ -7,7 +7,6 @@ const useInterval = (callback, delay) => {
7
7
  savedCallback.current = callback
8
8
  }, [callback])
9
9
 
10
- /* eslint-disable-next-line consistent-return */
11
10
  useEffect(() => {
12
11
  function tick() {
13
12
  savedCallback.current()
@@ -1,7 +1,7 @@
1
- import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'
2
- import { useSelector } from 'react-redux'
3
1
  import { useConfig } from 'domains/config/hooks'
4
2
  import { selectShowNotifications } from 'domains/store/selectors'
3
+ import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'
4
+ import { useSelector } from 'react-redux'
5
5
  import { textEntryControlName } from 'ui/components/entry/text-entry'
6
6
  import { useSeamlyServiceInfo } from './seamly-state-hooks'
7
7
  import beep from './sounds/beep.mp3'
@@ -45,7 +45,6 @@ const useNotification = () => {
45
45
  }, [permission, proactiveMessages, requestPermission])
46
46
 
47
47
  const sendNotification = useCallback(
48
- // eslint-disable-next-line no-undef
49
48
  async (title: string, options?: NotificationOptions) => {
50
49
  if (!showNotifications || !hasNotificationSupport) return
51
50
 
@@ -1,7 +1,7 @@
1
- import { useCallback, useEffect, useRef } from 'preact/hooks'
2
- import { useSelector } from 'react-redux'
3
1
  import { useI18n } from 'domains/i18n/hooks'
4
2
  import { useVisibility } from 'domains/visibility/hooks'
3
+ import { useCallback, useEffect, useRef } from 'preact/hooks'
4
+ import { useSelector } from 'react-redux'
5
5
  import useSeamlyCommands from 'ui/hooks/use-seamly-commands'
6
6
  import { selectShowInlineView } from '../../domains/visibility/selectors'
7
7
  import { useLiveRegion } from './live-region-hooks'
@@ -1,20 +1,20 @@
1
- import { useCallback } from 'preact/hooks'
2
1
  import { resetApp } from 'domains/app/actions'
3
2
  import { useUserHasResponded } from 'domains/app/hooks'
4
3
  import { setHasResponded } from 'domains/app/slice'
5
4
  import { setInterrupt } from 'domains/interrupt/slice'
6
5
  import { useAppDispatch } from 'domains/store'
7
6
  import { addEvent, setEvents, setInitialState } from 'domains/store/slice'
7
+ import type { MessageUpload } from 'domains/store/store.types'
8
8
  import { visibilityStates } from 'domains/visibility/constants'
9
9
  import { useVisibility } from 'domains/visibility/hooks'
10
10
  import { randomId } from 'lib/id'
11
+ import { useCallback } from 'preact/hooks'
11
12
  import useSeamlyEventBusContext from './event-bus-hooks'
12
13
  import {
13
14
  useSeamlyApiContext,
14
15
  useSeamlyHasConversation,
15
16
  } from './seamly-api-hooks'
16
17
  import { useSeamlyUnreadCount } from './seamly-state-hooks'
17
- import type { MessageUpload } from 'domains/store/store.types'
18
18
 
19
19
  const useSeamlyCommands = () => {
20
20
  const api = useSeamlyApiContext()
@@ -1,5 +1,5 @@
1
- import { useSyncExternalStore } from 'preact/compat'
2
1
  import ConversationConnector from 'api/conversation-connector'
2
+ import { useSyncExternalStore } from 'preact/compat'
3
3
  import { useSeamlyApiContext } from './seamly-api-hooks'
4
4
 
5
5
  const useSeamlyConversation = () => {