@qtoggle/qui 0.0.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 (202) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.json +492 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  5. package/.github/ISSUE_TEMPLATE/improvement_proposal.md +20 -0
  6. package/.github/workflows/main.yml +74 -0
  7. package/.pre-commit-config.yaml +8 -0
  8. package/LICENSE.txt +177 -0
  9. package/README.md +4 -0
  10. package/font/dejavusans-bold.woff +0 -0
  11. package/font/dejavusans-bolditalic.woff +0 -0
  12. package/font/dejavusans-italic.woff +0 -0
  13. package/font/dejavusans-regular.woff +0 -0
  14. package/img/qui-icons.svg +1937 -0
  15. package/js/base/base.js +47 -0
  16. package/js/base/condition-variable.js +92 -0
  17. package/js/base/errors.js +36 -0
  18. package/js/base/i18n.js +20 -0
  19. package/js/base/mixwith.js +135 -0
  20. package/js/base/require-js-compat.js +78 -0
  21. package/js/base/signal.js +91 -0
  22. package/js/base/singleton.js +66 -0
  23. package/js/base/timer.js +126 -0
  24. package/js/config.js +184 -0
  25. package/js/forms/common-fields/check-field.js +42 -0
  26. package/js/forms/common-fields/choice-buttons-field.js +30 -0
  27. package/js/forms/common-fields/color-combo-field.js +37 -0
  28. package/js/forms/common-fields/combo-field.js +108 -0
  29. package/js/forms/common-fields/common-fields.js +23 -0
  30. package/js/forms/common-fields/composite-field.js +132 -0
  31. package/js/forms/common-fields/custom-html-field.js +51 -0
  32. package/js/forms/common-fields/email-field.js +30 -0
  33. package/js/forms/common-fields/file-picker-field.js +46 -0
  34. package/js/forms/common-fields/jquery-ui-field.js +111 -0
  35. package/js/forms/common-fields/labels-field.js +69 -0
  36. package/js/forms/common-fields/numeric-field.js +39 -0
  37. package/js/forms/common-fields/password-field.js +28 -0
  38. package/js/forms/common-fields/phone-field.js +26 -0
  39. package/js/forms/common-fields/progress-disk-field.js +69 -0
  40. package/js/forms/common-fields/push-button-field.js +138 -0
  41. package/js/forms/common-fields/slider-field.js +51 -0
  42. package/js/forms/common-fields/text-area-field.js +34 -0
  43. package/js/forms/common-fields/text-field.js +89 -0
  44. package/js/forms/common-fields/up-down-field.js +85 -0
  45. package/js/forms/common-forms/common-forms.js +16 -0
  46. package/js/forms/common-forms/options-form.js +77 -0
  47. package/js/forms/common-forms/page-form.js +115 -0
  48. package/js/forms/form-button.js +202 -0
  49. package/js/forms/form-field.js +1183 -0
  50. package/js/forms/form.js +1181 -0
  51. package/js/forms/forms.js +68 -0
  52. package/js/global-glass.js +100 -0
  53. package/js/icons/default-stock.js +173 -0
  54. package/js/icons/icon.js +64 -0
  55. package/js/icons/icons.js +16 -0
  56. package/js/icons/multi-state-sprites-icon.js +362 -0
  57. package/js/icons/stock-icon.js +219 -0
  58. package/js/icons/stock.js +98 -0
  59. package/js/icons/stocks.js +57 -0
  60. package/js/index.js +232 -0
  61. package/js/lib/jquery.longpress.js +79 -0
  62. package/js/lib/jquery.module.js +4 -0
  63. package/js/lib/logger.module.js +4 -0
  64. package/js/lib/pep.module.js +4 -0
  65. package/js/lists/common-items/common-items.js +5 -0
  66. package/js/lists/common-items/icon-label-list-item.js +86 -0
  67. package/js/lists/common-lists/common-lists.js +5 -0
  68. package/js/lists/common-lists/page-list.js +53 -0
  69. package/js/lists/list-item.js +147 -0
  70. package/js/lists/list.js +636 -0
  71. package/js/lists/lists.js +26 -0
  72. package/js/main-ui/main-ui.js +64 -0
  73. package/js/main-ui/menu-bar.js +144 -0
  74. package/js/main-ui/options-bar.js +181 -0
  75. package/js/main-ui/status.js +185 -0
  76. package/js/main-ui/top-bar.js +59 -0
  77. package/js/messages/common-message-forms/common-message-forms.js +7 -0
  78. package/js/messages/common-message-forms/confirm-message-form.js +81 -0
  79. package/js/messages/common-message-forms/simple-message-form.js +67 -0
  80. package/js/messages/common-message-forms/sticky-simple-message-form.js +27 -0
  81. package/js/messages/message-form.js +107 -0
  82. package/js/messages/messages.js +21 -0
  83. package/js/messages/sticky-modal-page.js +98 -0
  84. package/js/messages/sticky-modal-progress-message.js +27 -0
  85. package/js/messages/toast.js +164 -0
  86. package/js/navigation.js +654 -0
  87. package/js/pages/breadcrumbs.js +124 -0
  88. package/js/pages/common-pages/common-pages.js +6 -0
  89. package/js/pages/common-pages/modal-progress-page.js +83 -0
  90. package/js/pages/common-pages/structured-page.js +46 -0
  91. package/js/pages/page.js +1018 -0
  92. package/js/pages/pages-context.js +154 -0
  93. package/js/pages/pages.js +252 -0
  94. package/js/pwa.js +337 -0
  95. package/js/sections/section.js +612 -0
  96. package/js/sections/sections.js +300 -0
  97. package/js/tables/common-cells/common-cells.js +7 -0
  98. package/js/tables/common-cells/icon-label-table-cell.js +68 -0
  99. package/js/tables/common-cells/push-button-table-cell.js +133 -0
  100. package/js/tables/common-cells/simple-table-cell.js +37 -0
  101. package/js/tables/common-tables/common-tables.js +5 -0
  102. package/js/tables/common-tables/page-table.js +55 -0
  103. package/js/tables/table-cell.js +198 -0
  104. package/js/tables/table-row.js +126 -0
  105. package/js/tables/table.js +492 -0
  106. package/js/tables/tables.js +36 -0
  107. package/js/theme.js +304 -0
  108. package/js/utils/ajax.js +126 -0
  109. package/js/utils/array.js +194 -0
  110. package/js/utils/colors.js +445 -0
  111. package/js/utils/cookies.js +65 -0
  112. package/js/utils/crypto.js +439 -0
  113. package/js/utils/css.js +234 -0
  114. package/js/utils/date.js +300 -0
  115. package/js/utils/files.js +27 -0
  116. package/js/utils/gestures.js +165 -0
  117. package/js/utils/html.js +76 -0
  118. package/js/utils/misc.js +81 -0
  119. package/js/utils/object.js +324 -0
  120. package/js/utils/promise.js +49 -0
  121. package/js/utils/string.js +192 -0
  122. package/js/utils/url.js +187 -0
  123. package/js/utils/utils.js +3 -0
  124. package/js/utils/visibility-manager.js +211 -0
  125. package/js/views/common-views/common-views.js +7 -0
  126. package/js/views/common-views/icon-label-view.js +210 -0
  127. package/js/views/common-views/progress-view.js +89 -0
  128. package/js/views/common-views/structured-view.js +368 -0
  129. package/js/views/view.js +467 -0
  130. package/js/views/views.js +3 -0
  131. package/js/widgets/base-widget.js +23 -0
  132. package/js/widgets/common-widgets/check-button.js +109 -0
  133. package/js/widgets/common-widgets/choice-buttons.js +322 -0
  134. package/js/widgets/common-widgets/color-combo.js +104 -0
  135. package/js/widgets/common-widgets/combo.js +645 -0
  136. package/js/widgets/common-widgets/common-widgets.js +17 -0
  137. package/js/widgets/common-widgets/email-input.js +7 -0
  138. package/js/widgets/common-widgets/file-picker.js +133 -0
  139. package/js/widgets/common-widgets/labels.js +132 -0
  140. package/js/widgets/common-widgets/numeric-input.js +49 -0
  141. package/js/widgets/common-widgets/password-input.js +91 -0
  142. package/js/widgets/common-widgets/phone-input.js +7 -0
  143. package/js/widgets/common-widgets/progress-disk.js +174 -0
  144. package/js/widgets/common-widgets/push-button.js +155 -0
  145. package/js/widgets/common-widgets/slider.js +455 -0
  146. package/js/widgets/common-widgets/text-area.js +52 -0
  147. package/js/widgets/common-widgets/text-input.js +174 -0
  148. package/js/widgets/common-widgets/up-down.js +351 -0
  149. package/js/widgets/widgets.js +57 -0
  150. package/js/window.js +557 -0
  151. package/jsdoc.conf.json +20 -0
  152. package/less/base.less +123 -0
  153. package/less/forms/common-fields.less +101 -0
  154. package/less/forms/common-forms.less +5 -0
  155. package/less/forms/form-button.less +21 -0
  156. package/less/forms/form-field.less +266 -0
  157. package/less/forms/form.less +131 -0
  158. package/less/global-glass.less +64 -0
  159. package/less/icon-label-view.less +82 -0
  160. package/less/icons.less +144 -0
  161. package/less/lists.less +105 -0
  162. package/less/main-ui.less +328 -0
  163. package/less/messages.less +189 -0
  164. package/less/no-effects.less +24 -0
  165. package/less/pages/breadcrumbs.less +98 -0
  166. package/less/pages/common-pages.less +36 -0
  167. package/less/pages/page.less +70 -0
  168. package/less/progress-view.less +51 -0
  169. package/less/stock-icons.less +43 -0
  170. package/less/structured-view.less +245 -0
  171. package/less/tables.less +84 -0
  172. package/less/theme-dark.less +133 -0
  173. package/less/theme-light.less +132 -0
  174. package/less/theme.less +419 -0
  175. package/less/visibility-manager.less +11 -0
  176. package/less/widgets/check-button.less +96 -0
  177. package/less/widgets/choice-buttons.less +160 -0
  178. package/less/widgets/color-combo.less +33 -0
  179. package/less/widgets/combo.less +230 -0
  180. package/less/widgets/common-buttons.less +120 -0
  181. package/less/widgets/common.less +24 -0
  182. package/less/widgets/input.less +258 -0
  183. package/less/widgets/labels.less +81 -0
  184. package/less/widgets/progress-disk.less +70 -0
  185. package/less/widgets/slider.less +199 -0
  186. package/less/widgets/updown.less +115 -0
  187. package/less/widgets/various.less +36 -0
  188. package/package.json +47 -0
  189. package/pyproject.toml +45 -0
  190. package/qui/__init__.py +110 -0
  191. package/qui/constants.py +1 -0
  192. package/qui/exceptions.py +2 -0
  193. package/qui/j2template.py +71 -0
  194. package/qui/settings.py +60 -0
  195. package/qui/templates/manifest.json +25 -0
  196. package/qui/templates/qui.html +126 -0
  197. package/qui/templates/service-worker.js +188 -0
  198. package/qui/web/__init__.py +0 -0
  199. package/qui/web/tornado.py +220 -0
  200. package/scripts/postinstall.sh +10 -0
  201. package/webpack/webpack-adjust-css-urls-loader.js +36 -0
  202. package/webpack/webpack-common.js +384 -0
@@ -0,0 +1,81 @@
1
+
2
+ import {gettext} from '$qui/base/i18n.js'
3
+ import FormButton from '$qui/forms/form-button.js'
4
+ import StockIcon from '$qui/icons/stock-icon.js'
5
+ import {asap} from '$qui/utils/misc.js'
6
+ import * as ObjectUtils from '$qui/utils/object.js'
7
+
8
+ import MessageForm from '../message-form.js'
9
+
10
+
11
+ /**
12
+ * A message form asking the user for confirmation.
13
+ * @alias qui.messages.commonmessageforms.ConfirmMessageForm
14
+ * @extends qui.messages.MessageForm
15
+ */
16
+ class ConfirmMessageForm extends MessageForm {
17
+
18
+ /**
19
+ * @constructs
20
+ * @param {qui.messages.MessageForm.Callback} [onYes] an optional confirmation callback
21
+ * @param {qui.messages.MessageForm.Callback} [onNo] an optional decline callback
22
+ * @param {...*} args parent class parameters
23
+ */
24
+ constructor({onYes = null, onNo = null, ...args}) {
25
+ ObjectUtils.assignDefault(args, {
26
+ icon: new StockIcon({name: 'qmark'}),
27
+ buttons: [
28
+ new FormButton({id: 'no', caption: gettext('No'), cancel: true}),
29
+ new FormButton({id: 'yes', caption: gettext('Yes'), def: true})
30
+ ]
31
+ })
32
+
33
+ super(args)
34
+
35
+ this._onYes = onYes
36
+ this._onNo = onNo
37
+
38
+ this._resolve = null
39
+ this._reject = null
40
+
41
+ this._confirmed = false
42
+ }
43
+
44
+ applyData() {
45
+ this._confirmed = true
46
+ }
47
+
48
+ onClose() {
49
+ if (this._confirmed) {
50
+ if (this._onYes) {
51
+ asap(this._onYes)
52
+ }
53
+ if (this._resolve) {
54
+ asap(this._resolve)
55
+ }
56
+ }
57
+ else {
58
+ if (this._onNo) {
59
+ asap(this._onNo)
60
+ }
61
+ if (this._reject) {
62
+ asap(this._reject)
63
+ }
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Return a promise resolves on positive answer and is rejected on negative answer.
69
+ * @returns {Promise}
70
+ */
71
+ asPromise() {
72
+ return new Promise(function (resolve, reject) {
73
+ this._resolve = resolve
74
+ this._reject = reject
75
+ }.bind(this))
76
+ }
77
+
78
+ }
79
+
80
+
81
+ export default ConfirmMessageForm
@@ -0,0 +1,67 @@
1
+
2
+ import {gettext} from '$qui/base/i18n.js'
3
+ import FormButton from '$qui/forms/form-button.js'
4
+ import StockIcon from '$qui/icons/stock-icon.js'
5
+ import {asap} from '$qui/utils/misc.js'
6
+ import * as ObjectUtils from '$qui/utils/object.js'
7
+
8
+ import MessageForm from '../message-form.js'
9
+
10
+
11
+ /**
12
+ * A simple message form.
13
+ * @alias qui.messages.commonmessageforms.SimpleMessageForm
14
+ * @extends qui.messages.MessageForm
15
+ */
16
+ class SimpleMessageForm extends MessageForm {
17
+
18
+ /**
19
+ * @constructs
20
+ * @param {String} type message type (`"info"`, `"warning"` or `"error"`)
21
+ * @param {String} [buttonCaption] optional button caption (defaults to `"OK"`)
22
+ * @param {qui.messages.MessageForm.Callback} [onClose] a dismiss callback
23
+ * @param {...*} args parent class parameters
24
+ */
25
+ constructor({type, buttonCaption = gettext('OK'), onClose = null, ...args}) {
26
+ let variant = null
27
+ let iconName = null
28
+ switch (type) {
29
+ case 'info':
30
+ variant = 'foreground'
31
+ iconName = 'info'
32
+ break
33
+
34
+ case 'warning':
35
+ variant = 'warning'
36
+ iconName = 'exclam'
37
+ break
38
+
39
+ case 'error':
40
+ variant = 'error'
41
+ iconName = 'exclam'
42
+ break
43
+ }
44
+
45
+ if (iconName && variant && args.icon == null) {
46
+ args.icon = new StockIcon({name: iconName, variant: variant})
47
+ }
48
+
49
+ ObjectUtils.setDefault(args, 'buttons', [
50
+ new FormButton({id: 'ok', caption: buttonCaption, def: true, style: 'interactive'})
51
+ ])
52
+
53
+ super(args)
54
+
55
+ this._onClose = onClose
56
+ }
57
+
58
+ onClose() {
59
+ if (this._onClose) {
60
+ asap(this._onClose)
61
+ }
62
+ }
63
+
64
+ }
65
+
66
+
67
+ export default SimpleMessageForm
@@ -0,0 +1,27 @@
1
+
2
+ import {mix} from '$qui/base/mixwith.js'
3
+
4
+ import SimpleMessageForm from './simple-message-form.js'
5
+ import StickyModalPageMixin from '../sticky-modal-page.js'
6
+
7
+
8
+ /**
9
+ * A sticky modal variant of {@link qui.messages.commonmessageforms.SimpleMessageForm}.
10
+ * @alias qui.messages.commonmessageforms.StickySimpleMessageForm
11
+ * @extends qui.messages.commonmessageforms.SimpleMessageForm
12
+ * @mixes qui.messages.StickyModalPageMixin
13
+ */
14
+ class StickySimpleMessageForm extends mix(SimpleMessageForm).with(StickyModalPageMixin) {
15
+
16
+ /**
17
+ * @constructs
18
+ * @param {...*} args parent class parameters
19
+ */
20
+ constructor({...args}) {
21
+ super(args)
22
+ }
23
+
24
+ }
25
+
26
+
27
+ export default StickySimpleMessageForm
@@ -0,0 +1,107 @@
1
+
2
+ import $ from '$qui/lib/jquery.module.js'
3
+
4
+ import {AssertionError} from '$qui/base/errors.js'
5
+ import {PageForm} from '$qui/forms/common-forms/common-forms.js'
6
+ import StockIcon from '$qui/icons/stock-icon.js'
7
+ import * as Sections from '$qui/sections/sections.js'
8
+ import {asap} from '$qui/utils/misc.js'
9
+ import * as ObjectUtils from '$qui/utils/object.js'
10
+
11
+
12
+ /**
13
+ * Message form callback.
14
+ * @callback qui.messages.MessageForm.Callback
15
+ * @param {*} result
16
+ */
17
+
18
+ /**
19
+ * A base class for message forms.
20
+ * @alias qui.messages.MessageForm
21
+ * @extends qui.forms.commonforms.PageForm
22
+ */
23
+ class MessageForm extends PageForm {
24
+
25
+ /**
26
+ * @constructs
27
+ * @param {String} message the message
28
+ * @param {qui.icons.Icon} [icon] an optional icon
29
+ * @param {...*} args parent class parameters
30
+ */
31
+ constructor({message, icon = null, ...args}) {
32
+ ObjectUtils.assignDefault(args, {
33
+ popup: true,
34
+ transparent: true,
35
+ topless: true,
36
+ width: '30em',
37
+ valuesWidth: 100,
38
+ title: args.message
39
+ })
40
+
41
+ super(args)
42
+
43
+ this._message = message
44
+ this._icon = icon
45
+ }
46
+
47
+ makeBody() {
48
+ return super.makeBody().append(this.makeMessageBody())
49
+ }
50
+
51
+ /**
52
+ * Override this to indicate how the message body is built.
53
+ * @returns {jQuery}
54
+ */
55
+ makeMessageBody() {
56
+ let bodyDiv = $('<div></div>', {class: 'qui-message-form-body'})
57
+ let labelSpan = $('<div></div>', {class: 'qui-message-form-label'})
58
+
59
+ labelSpan.html(this._message)
60
+
61
+ if (this._icon) {
62
+ let iconDiv = $('<div></div>', {class: 'qui-icon qui-message-form-icon'})
63
+ let icon = this._icon
64
+ if (icon instanceof StockIcon) {
65
+ icon = icon.alterDefault({variant: 'foreground'})
66
+ }
67
+ icon.applyTo(iconDiv)
68
+ bodyDiv.append(iconDiv)
69
+ }
70
+
71
+ bodyDiv.append(labelSpan)
72
+
73
+ return bodyDiv
74
+ }
75
+
76
+ handleBecomeCurrent() {
77
+ super.handleBecomeCurrent()
78
+
79
+ /* Focus the default button */
80
+ asap(function () {
81
+ let button = this.getButtons().find(b => b.isDefault())
82
+ if (button) {
83
+ button.focus()
84
+ }
85
+ }.bind(this))
86
+ }
87
+
88
+ /**
89
+ * Show the message form by pushing it onto the current section context.
90
+ * @returns {qui.messages.MessageForm} this form
91
+ */
92
+
93
+ show() {
94
+ let currentSection = Sections.getCurrent()
95
+ if (!currentSection) {
96
+ throw new AssertionError('Attempt to show message form while no current section')
97
+ }
98
+
99
+ currentSection.pushPage(this)
100
+
101
+ return this
102
+ }
103
+
104
+ }
105
+
106
+
107
+ export default MessageForm
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @namespace qui.messages
3
+ */
4
+
5
+ import * as Toast from './toast.js'
6
+
7
+
8
+ /**
9
+ * Wrap a text into label markup.
10
+ * @alias qui.messages.wrapLabel
11
+ * @param {String} text the text to wrap
12
+ * @returns {String} the label
13
+ */
14
+ export function wrapLabel(text) {
15
+ return `<span class="qui-message-label">${text}</span>`
16
+ }
17
+
18
+
19
+ export function init() {
20
+ Toast.init()
21
+ }
@@ -0,0 +1,98 @@
1
+
2
+ import {Mixin} from '$qui/base/mixwith.js'
3
+ import * as GlobalGlass from '$qui/global-glass.js'
4
+
5
+
6
+ /** @lends qui.messages.StickyModalPageMixin */
7
+ const StickyModalPageMixin = Mixin((superclass = Object) => {
8
+
9
+ /**
10
+ * A mixin for pages that are stuck to the global glass until explicitly removed.
11
+ * @alias qui.messages.StickyModalPageMixin
12
+ * @mixin
13
+ */
14
+ class StickyModalPageMixin extends superclass {
15
+
16
+ /**
17
+ * @constructs
18
+ * @param {...*} args parent class parameters
19
+ */
20
+ constructor({...args} = {}) {
21
+ super(args)
22
+
23
+ this._showCount = 0
24
+ }
25
+
26
+ initPageHTML(html) {
27
+ super.initPageHTML(html)
28
+ html.addClass('sticky')
29
+ }
30
+
31
+ close() {
32
+ /* Call the hide method instead of page's close */
33
+ this.hide()
34
+ this.onClose()
35
+ }
36
+
37
+ /**
38
+ * Override this method to indicate how the page is reset to its initial state, as soon as it is shown.
39
+ */
40
+ reset() {
41
+ }
42
+
43
+ /**
44
+ * Show this page.
45
+ *
46
+ * This is a reentrant method.
47
+ *
48
+ * @returns {qui.messages.StickyModalPageMixin} this page
49
+ */
50
+ show() {
51
+ if (this._showCount === 0) {
52
+ this.attach()
53
+ this.getPageHTML().addClass('visible')
54
+ GlobalGlass.updateVisibility()
55
+
56
+ this.handleBecomeCurrent()
57
+ }
58
+
59
+ this._showCount++
60
+ this.reset()
61
+
62
+ return this
63
+ }
64
+
65
+ /**
66
+ * Hide a previously shown page.
67
+ *
68
+ * This method should be called as many times as its counterpart {@link qui.messages.StickyModalPageMixin#show}
69
+ * method has been called, before it actually hides the page.
70
+ */
71
+ hide() {
72
+ this._showCount--
73
+
74
+ if (this._showCount === 0) {
75
+ this.detach()
76
+ this.getPageHTML().removeClass('visible')
77
+ GlobalGlass.updateVisibility()
78
+
79
+ this.handleLeaveCurrent()
80
+ }
81
+ }
82
+
83
+ handleBecomeCurrent() {
84
+ this.onBecomeCurrent()
85
+ }
86
+
87
+ handleLeaveCurrent() {
88
+ this.onLeaveCurrent()
89
+ }
90
+
91
+ }
92
+
93
+ return StickyModalPageMixin
94
+
95
+ })
96
+
97
+
98
+ export default StickyModalPageMixin
@@ -0,0 +1,27 @@
1
+
2
+ import {mix} from '$qui/base/mixwith.js'
3
+ import {ModalProgressPage} from '$qui/pages/common-pages/common-pages.js'
4
+
5
+ import StickyModalPageMixin from './sticky-modal-page.js'
6
+
7
+
8
+ /**
9
+ * A sticky modal progress page.
10
+ * @alias qui.messages.StickyModalProgressMessage
11
+ * @extends qui.pages.commonpages.ModalProgressPage
12
+ * @mixes qui.messages.StickyModalPageMixin
13
+ */
14
+ class StickyModalProgressMessage extends mix(ModalProgressPage).with(StickyModalPageMixin) {
15
+
16
+ /**
17
+ * @constructs
18
+ * @param {...*} args parent class parameters
19
+ */
20
+ constructor({...args} = {}) {
21
+ super(args)
22
+ }
23
+
24
+ }
25
+
26
+
27
+ export default StickyModalProgressMessage
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @namespace qui.messages.toast
3
+ */
4
+
5
+ import $ from '$qui/lib/jquery.module.js'
6
+
7
+ import StockIcon from '$qui/icons/stock-icon.js'
8
+ import * as Theme from '$qui/theme.js'
9
+ import {asap} from '$qui/utils/misc.js'
10
+ import * as Window from '$qui/window.js'
11
+
12
+
13
+ const TOAST_MESSAGE_TIMEOUT = 5000 /* 5 seconds */
14
+
15
+ let toastMessageTimeoutHandle = null
16
+ let toastMessageContainer = null
17
+ let toastMessageShowingTimeoutHandle = null
18
+
19
+
20
+ /**
21
+ * Show a toast message for a limited period of time.
22
+ * @alias qui.messages.toast.show
23
+ * @param {?String|jQuery} message the message to show
24
+ * @param {?String} type message type (`"info"`, `"warning"` or `"error"`)
25
+ * @param {Number} [timeout] the message display timeout, in milliseconds (defaults to 5 seconds)
26
+ * @param {Boolean} [closeable] whether the message can be closed by the user (defaults to `true`)
27
+ */
28
+ export function show({message, type, timeout = TOAST_MESSAGE_TIMEOUT, closeable = true}) {
29
+ let messageSpan = toastMessageContainer.find('span.qui-toast-message')
30
+
31
+ if (toastMessageTimeoutHandle) {
32
+ clearTimeout(toastMessageTimeoutHandle)
33
+ toastMessageTimeoutHandle = null
34
+ }
35
+
36
+ if (message) {
37
+ Window.$body.addClass('toast-message-visible')
38
+ toastMessageContainer.removeClass('info warning error multiline closeable')
39
+
40
+ messageSpan.html(message)
41
+ if (type) {
42
+ toastMessageContainer.addClass(type)
43
+ }
44
+
45
+ /* Test if the message wraps */
46
+ let normalHeight = messageSpan.height()
47
+ toastMessageContainer.find('div.qui-toast-message').css('white-space', 'normal')
48
+ let wrappedHeight = messageSpan.height()
49
+ toastMessageContainer.find('div.qui-toast-message').css('white-space', '')
50
+
51
+ if (normalHeight < wrappedHeight) {
52
+ toastMessageContainer.addClass('multiline')
53
+ }
54
+
55
+ if (timeout !== 0) {
56
+ toastMessageTimeoutHandle = setTimeout(function () {
57
+ show({message: null, type: 'info'})
58
+ }, timeout)
59
+ }
60
+
61
+ if (closeable !== false) {
62
+ toastMessageContainer.addClass('closeable')
63
+ }
64
+
65
+ /* Showing flag timeout */
66
+ if (toastMessageShowingTimeoutHandle) {
67
+ clearTimeout(toastMessageShowingTimeoutHandle)
68
+ }
69
+
70
+ toastMessageShowingTimeoutHandle = asap(function () {
71
+ toastMessageShowingTimeoutHandle = null
72
+ })
73
+ }
74
+ else if (Window.$body.hasClass('toast-message-visible')) { /* Hide */
75
+ Window.$body.removeClass('toast-message-visible')
76
+ Theme.afterTransition(function () {
77
+ if (Window.$body.hasClass('toast-message-visible')) {
78
+ return /* Reshown in the meantime */
79
+ }
80
+
81
+ messageSpan.html('')
82
+ toastMessageContainer.removeClass('info warning error multiline')
83
+ })
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Hide a currently displayed toast message.
89
+ * @alias qui.messages.toast.hide
90
+ */
91
+ export function hide() {
92
+ show({message: null, type: 'info'})
93
+ }
94
+
95
+ /**
96
+ * Convenience function for {@link qui.messages.toast.show} with default timeout and type `"info"`.
97
+ * @alias qui.messages.toast.info
98
+ * @param {String|jQuery} message the message to show
99
+ */
100
+ export function info(message) {
101
+ show({message: message, type: 'info'})
102
+ }
103
+
104
+ /**
105
+ * Convenience function for {@link qui.messages.toast.show} with default timeout and type `"warning"`.
106
+ * @alias qui.messages.toast.warning
107
+ * @param {String|jQuery} message the message to show
108
+ */
109
+ export function warning(message) {
110
+ show({message: message, type: 'warning'})
111
+ }
112
+
113
+ /**
114
+ * Convenience function for {@link qui.messages.toast.show} with default timeout and type `"error"`.
115
+ * @alias qui.messages.toast.error
116
+ * @param {String|jQuery} message the message to show
117
+ */
118
+ export function error(message) {
119
+ show({message: message, type: 'error'})
120
+ }
121
+
122
+
123
+ export function init() {
124
+ toastMessageContainer = $('<div></div>', {class: 'qui-toast-message-container'})
125
+ toastMessageContainer.append($('<div></div>', {class: 'qui-toast-message-icon'}))
126
+
127
+ let messageDiv = $('<div></div>', {class: 'qui-toast-message'})
128
+ messageDiv.append($('<span></span>', {class: 'qui-toast-message'}))
129
+ messageDiv.append($('<div></div>', {class: 'qui-base-button qui-toast-message-close-button'}))
130
+ toastMessageContainer.append(messageDiv)
131
+
132
+ Window.$body.append(toastMessageContainer)
133
+
134
+ /* Close button */
135
+ let closeButton = toastMessageContainer.find('div.qui-toast-message-close-button')
136
+ new StockIcon({
137
+ name: 'close', variant: 'interactive', activeVariant: 'interactive-active'
138
+ }).alter({scale: 0.75}).applyTo(closeButton)
139
+
140
+ closeButton.on('click', function () {
141
+ show({message: null, type: null})
142
+ })
143
+
144
+ /* Close when clicked anywhere */
145
+ Window.$body.on('click', function (e) {
146
+ if (toastMessageShowingTimeoutHandle) {
147
+ return /* Showing is in progress */
148
+ }
149
+
150
+ if (!Window.$body.hasClass('toast-message-visible')) {
151
+ return /* Message not visible */
152
+ }
153
+
154
+ if (!toastMessageContainer.hasClass('closeable')) {
155
+ return /* Message not closeable */
156
+ }
157
+
158
+ if (toastMessageContainer.has(e.target).length) {
159
+ return /* Clicked on the message container itself */
160
+ }
161
+
162
+ show({message: null, type: null})
163
+ })
164
+ }