@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.
- package/.eslintignore +2 -0
- package/.eslintrc.json +492 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- package/.github/ISSUE_TEMPLATE/improvement_proposal.md +20 -0
- package/.github/workflows/main.yml +74 -0
- package/.pre-commit-config.yaml +8 -0
- package/LICENSE.txt +177 -0
- package/README.md +4 -0
- package/font/dejavusans-bold.woff +0 -0
- package/font/dejavusans-bolditalic.woff +0 -0
- package/font/dejavusans-italic.woff +0 -0
- package/font/dejavusans-regular.woff +0 -0
- package/img/qui-icons.svg +1937 -0
- package/js/base/base.js +47 -0
- package/js/base/condition-variable.js +92 -0
- package/js/base/errors.js +36 -0
- package/js/base/i18n.js +20 -0
- package/js/base/mixwith.js +135 -0
- package/js/base/require-js-compat.js +78 -0
- package/js/base/signal.js +91 -0
- package/js/base/singleton.js +66 -0
- package/js/base/timer.js +126 -0
- package/js/config.js +184 -0
- package/js/forms/common-fields/check-field.js +42 -0
- package/js/forms/common-fields/choice-buttons-field.js +30 -0
- package/js/forms/common-fields/color-combo-field.js +37 -0
- package/js/forms/common-fields/combo-field.js +108 -0
- package/js/forms/common-fields/common-fields.js +23 -0
- package/js/forms/common-fields/composite-field.js +132 -0
- package/js/forms/common-fields/custom-html-field.js +51 -0
- package/js/forms/common-fields/email-field.js +30 -0
- package/js/forms/common-fields/file-picker-field.js +46 -0
- package/js/forms/common-fields/jquery-ui-field.js +111 -0
- package/js/forms/common-fields/labels-field.js +69 -0
- package/js/forms/common-fields/numeric-field.js +39 -0
- package/js/forms/common-fields/password-field.js +28 -0
- package/js/forms/common-fields/phone-field.js +26 -0
- package/js/forms/common-fields/progress-disk-field.js +69 -0
- package/js/forms/common-fields/push-button-field.js +138 -0
- package/js/forms/common-fields/slider-field.js +51 -0
- package/js/forms/common-fields/text-area-field.js +34 -0
- package/js/forms/common-fields/text-field.js +89 -0
- package/js/forms/common-fields/up-down-field.js +85 -0
- package/js/forms/common-forms/common-forms.js +16 -0
- package/js/forms/common-forms/options-form.js +77 -0
- package/js/forms/common-forms/page-form.js +115 -0
- package/js/forms/form-button.js +202 -0
- package/js/forms/form-field.js +1183 -0
- package/js/forms/form.js +1181 -0
- package/js/forms/forms.js +68 -0
- package/js/global-glass.js +100 -0
- package/js/icons/default-stock.js +173 -0
- package/js/icons/icon.js +64 -0
- package/js/icons/icons.js +16 -0
- package/js/icons/multi-state-sprites-icon.js +362 -0
- package/js/icons/stock-icon.js +219 -0
- package/js/icons/stock.js +98 -0
- package/js/icons/stocks.js +57 -0
- package/js/index.js +232 -0
- package/js/lib/jquery.longpress.js +79 -0
- package/js/lib/jquery.module.js +4 -0
- package/js/lib/logger.module.js +4 -0
- package/js/lib/pep.module.js +4 -0
- package/js/lists/common-items/common-items.js +5 -0
- package/js/lists/common-items/icon-label-list-item.js +86 -0
- package/js/lists/common-lists/common-lists.js +5 -0
- package/js/lists/common-lists/page-list.js +53 -0
- package/js/lists/list-item.js +147 -0
- package/js/lists/list.js +636 -0
- package/js/lists/lists.js +26 -0
- package/js/main-ui/main-ui.js +64 -0
- package/js/main-ui/menu-bar.js +144 -0
- package/js/main-ui/options-bar.js +181 -0
- package/js/main-ui/status.js +185 -0
- package/js/main-ui/top-bar.js +59 -0
- package/js/messages/common-message-forms/common-message-forms.js +7 -0
- package/js/messages/common-message-forms/confirm-message-form.js +81 -0
- package/js/messages/common-message-forms/simple-message-form.js +67 -0
- package/js/messages/common-message-forms/sticky-simple-message-form.js +27 -0
- package/js/messages/message-form.js +107 -0
- package/js/messages/messages.js +21 -0
- package/js/messages/sticky-modal-page.js +98 -0
- package/js/messages/sticky-modal-progress-message.js +27 -0
- package/js/messages/toast.js +164 -0
- package/js/navigation.js +654 -0
- package/js/pages/breadcrumbs.js +124 -0
- package/js/pages/common-pages/common-pages.js +6 -0
- package/js/pages/common-pages/modal-progress-page.js +83 -0
- package/js/pages/common-pages/structured-page.js +46 -0
- package/js/pages/page.js +1018 -0
- package/js/pages/pages-context.js +154 -0
- package/js/pages/pages.js +252 -0
- package/js/pwa.js +337 -0
- package/js/sections/section.js +612 -0
- package/js/sections/sections.js +300 -0
- package/js/tables/common-cells/common-cells.js +7 -0
- package/js/tables/common-cells/icon-label-table-cell.js +68 -0
- package/js/tables/common-cells/push-button-table-cell.js +133 -0
- package/js/tables/common-cells/simple-table-cell.js +37 -0
- package/js/tables/common-tables/common-tables.js +5 -0
- package/js/tables/common-tables/page-table.js +55 -0
- package/js/tables/table-cell.js +198 -0
- package/js/tables/table-row.js +126 -0
- package/js/tables/table.js +492 -0
- package/js/tables/tables.js +36 -0
- package/js/theme.js +304 -0
- package/js/utils/ajax.js +126 -0
- package/js/utils/array.js +194 -0
- package/js/utils/colors.js +445 -0
- package/js/utils/cookies.js +65 -0
- package/js/utils/crypto.js +439 -0
- package/js/utils/css.js +234 -0
- package/js/utils/date.js +300 -0
- package/js/utils/files.js +27 -0
- package/js/utils/gestures.js +165 -0
- package/js/utils/html.js +76 -0
- package/js/utils/misc.js +81 -0
- package/js/utils/object.js +324 -0
- package/js/utils/promise.js +49 -0
- package/js/utils/string.js +192 -0
- package/js/utils/url.js +187 -0
- package/js/utils/utils.js +3 -0
- package/js/utils/visibility-manager.js +211 -0
- package/js/views/common-views/common-views.js +7 -0
- package/js/views/common-views/icon-label-view.js +210 -0
- package/js/views/common-views/progress-view.js +89 -0
- package/js/views/common-views/structured-view.js +368 -0
- package/js/views/view.js +467 -0
- package/js/views/views.js +3 -0
- package/js/widgets/base-widget.js +23 -0
- package/js/widgets/common-widgets/check-button.js +109 -0
- package/js/widgets/common-widgets/choice-buttons.js +322 -0
- package/js/widgets/common-widgets/color-combo.js +104 -0
- package/js/widgets/common-widgets/combo.js +645 -0
- package/js/widgets/common-widgets/common-widgets.js +17 -0
- package/js/widgets/common-widgets/email-input.js +7 -0
- package/js/widgets/common-widgets/file-picker.js +133 -0
- package/js/widgets/common-widgets/labels.js +132 -0
- package/js/widgets/common-widgets/numeric-input.js +49 -0
- package/js/widgets/common-widgets/password-input.js +91 -0
- package/js/widgets/common-widgets/phone-input.js +7 -0
- package/js/widgets/common-widgets/progress-disk.js +174 -0
- package/js/widgets/common-widgets/push-button.js +155 -0
- package/js/widgets/common-widgets/slider.js +455 -0
- package/js/widgets/common-widgets/text-area.js +52 -0
- package/js/widgets/common-widgets/text-input.js +174 -0
- package/js/widgets/common-widgets/up-down.js +351 -0
- package/js/widgets/widgets.js +57 -0
- package/js/window.js +557 -0
- package/jsdoc.conf.json +20 -0
- package/less/base.less +123 -0
- package/less/forms/common-fields.less +101 -0
- package/less/forms/common-forms.less +5 -0
- package/less/forms/form-button.less +21 -0
- package/less/forms/form-field.less +266 -0
- package/less/forms/form.less +131 -0
- package/less/global-glass.less +64 -0
- package/less/icon-label-view.less +82 -0
- package/less/icons.less +144 -0
- package/less/lists.less +105 -0
- package/less/main-ui.less +328 -0
- package/less/messages.less +189 -0
- package/less/no-effects.less +24 -0
- package/less/pages/breadcrumbs.less +98 -0
- package/less/pages/common-pages.less +36 -0
- package/less/pages/page.less +70 -0
- package/less/progress-view.less +51 -0
- package/less/stock-icons.less +43 -0
- package/less/structured-view.less +245 -0
- package/less/tables.less +84 -0
- package/less/theme-dark.less +133 -0
- package/less/theme-light.less +132 -0
- package/less/theme.less +419 -0
- package/less/visibility-manager.less +11 -0
- package/less/widgets/check-button.less +96 -0
- package/less/widgets/choice-buttons.less +160 -0
- package/less/widgets/color-combo.less +33 -0
- package/less/widgets/combo.less +230 -0
- package/less/widgets/common-buttons.less +120 -0
- package/less/widgets/common.less +24 -0
- package/less/widgets/input.less +258 -0
- package/less/widgets/labels.less +81 -0
- package/less/widgets/progress-disk.less +70 -0
- package/less/widgets/slider.less +199 -0
- package/less/widgets/updown.less +115 -0
- package/less/widgets/various.less +36 -0
- package/package.json +47 -0
- package/pyproject.toml +45 -0
- package/qui/__init__.py +110 -0
- package/qui/constants.py +1 -0
- package/qui/exceptions.py +2 -0
- package/qui/j2template.py +71 -0
- package/qui/settings.py +60 -0
- package/qui/templates/manifest.json +25 -0
- package/qui/templates/qui.html +126 -0
- package/qui/templates/service-worker.js +188 -0
- package/qui/web/__init__.py +0 -0
- package/qui/web/tornado.py +220 -0
- package/scripts/postinstall.sh +10 -0
- package/webpack/webpack-adjust-css-urls-loader.js +36 -0
- package/webpack/webpack-common.js +384 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
|
|
2
|
+
@import (reference) "../base";
|
|
3
|
+
@import (reference) "../theme";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
div.qui-progress-disk-container {
|
|
7
|
+
position: relative;
|
|
8
|
+
|
|
9
|
+
& > svg {
|
|
10
|
+
transform: rotate(-90deg);
|
|
11
|
+
vertical-align: top;
|
|
12
|
+
|
|
13
|
+
& > ellipse.qui-progress-disk-ring {
|
|
14
|
+
opacity: 0.2;
|
|
15
|
+
fill: transparent;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
& > path.qui-progress-disk-cursor {
|
|
19
|
+
fill: transparent;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
& > div.qui-progress-disk-label {
|
|
25
|
+
position: absolute;
|
|
26
|
+
width: 100%;
|
|
27
|
+
top: 0;
|
|
28
|
+
left: 0;
|
|
29
|
+
text-align: center;
|
|
30
|
+
font-size: 90%;
|
|
31
|
+
|
|
32
|
+
&.small {
|
|
33
|
+
font-size: 50%;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&.no-value > svg {
|
|
39
|
+
transform: rotate(0deg);
|
|
40
|
+
animation: spin 1s linear infinite;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&.has-warning {
|
|
44
|
+
|
|
45
|
+
& > svg > ellipse.qui-progress-disk-ring,
|
|
46
|
+
& > svg > path.qui-progress-disk-cursor {
|
|
47
|
+
stroke: @warning-color !important;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&.has-error {
|
|
53
|
+
|
|
54
|
+
& > svg > ellipse.qui-progress-disk-ring,
|
|
55
|
+
& > svg > path.qui-progress-disk-cursor {
|
|
56
|
+
stroke: @error-color !important;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&.disabled {
|
|
62
|
+
|
|
63
|
+
& > svg > ellipse.qui-progress-disk-ring,
|
|
64
|
+
& > svg > path.qui-progress-disk-cursor {
|
|
65
|
+
stroke: @disabled-color !important;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
|
|
2
|
+
@import (reference) "../base";
|
|
3
|
+
@import (reference) "../theme";
|
|
4
|
+
@import (reference) "common";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
div.qui-slider {
|
|
8
|
+
padding: 0.5em 0.8em 0.8em 0.8em;
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
.noselect;
|
|
11
|
+
|
|
12
|
+
& > div.qui-slider-labels {
|
|
13
|
+
position: relative;
|
|
14
|
+
white-space: nowrap;
|
|
15
|
+
height: 1.8em;
|
|
16
|
+
margin: 0 0.5em;
|
|
17
|
+
|
|
18
|
+
& > span.qui-slider-label {
|
|
19
|
+
width: 30%;
|
|
20
|
+
text-align: center;
|
|
21
|
+
position: absolute;
|
|
22
|
+
font-size: 0.85em;
|
|
23
|
+
opacity: 1;
|
|
24
|
+
transition: opacity @transition-duration ease,
|
|
25
|
+
color @transition-duration ease;
|
|
26
|
+
|
|
27
|
+
&.qui-slider-cursor-label {
|
|
28
|
+
color: @interactive-color;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&.overlapped {
|
|
32
|
+
opacity: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&:NOT(.all-ticks-visible) {
|
|
38
|
+
|
|
39
|
+
& > span.qui-slider-cursor-label {
|
|
40
|
+
background: linear-gradient(to right,
|
|
41
|
+
transparent 0%, @background-color 25%,
|
|
42
|
+
@background-color 75%, transparent 100%);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&.all-ticks-visible {
|
|
48
|
+
|
|
49
|
+
& > span.qui-slider-label {
|
|
50
|
+
transition: none;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
& > div.qui-slider-bar-container {
|
|
58
|
+
padding: 0 0.5em;
|
|
59
|
+
|
|
60
|
+
& > div.qui-slider-bar {
|
|
61
|
+
position: relative;
|
|
62
|
+
height: 0.5em;
|
|
63
|
+
border: 0.0625em solid @interactive-color;
|
|
64
|
+
border-radius: 0.2em;
|
|
65
|
+
transition: border-color @transition-duration linear;
|
|
66
|
+
|
|
67
|
+
& > div.qui-slider-cursor {
|
|
68
|
+
position: absolute;
|
|
69
|
+
left: 0;
|
|
70
|
+
top: -0.5em;
|
|
71
|
+
width: 1.5em;
|
|
72
|
+
height: 1.5em;
|
|
73
|
+
margin-left: -0.75em;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
border-width: 0;
|
|
76
|
+
border-radius: 0.2em;
|
|
77
|
+
background: @interactive-color;
|
|
78
|
+
transition+: background @transition-duration ease;
|
|
79
|
+
.qui-focusable-widget();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
& > div.qui-slider-cursor.active {
|
|
83
|
+
background: @interactive-active-color;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
&:FOCUS {
|
|
91
|
+
|
|
92
|
+
& > div.qui-slider-bar-container > div.qui-slider-bar > div.qui-slider-cursor {
|
|
93
|
+
.qui-focused-widget();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
&.active {
|
|
99
|
+
|
|
100
|
+
& > div.qui-slider-labels {
|
|
101
|
+
|
|
102
|
+
& > span.qui-slider-label.overlapped:NOT(.completely-overlapped) {
|
|
103
|
+
opacity: 1;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&.has-warning {
|
|
111
|
+
|
|
112
|
+
& > div.qui-slider-bar-container > div.qui-slider-bar {
|
|
113
|
+
border-color: @warning-color;
|
|
114
|
+
|
|
115
|
+
& > div.qui-slider-cursor {
|
|
116
|
+
background: @warning-color;
|
|
117
|
+
|
|
118
|
+
&.active {
|
|
119
|
+
background: @warning-active-color;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
&:FOCUS > div.qui-slider-bar-container > div.qui-slider-bar > div.qui-slider-cursor {
|
|
127
|
+
.qui-focused-widget-warning();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
&.has-error {
|
|
133
|
+
|
|
134
|
+
& > div.qui-slider-bar-container > div.qui-slider-bar {
|
|
135
|
+
border-color: @error-color;
|
|
136
|
+
|
|
137
|
+
& > div.qui-slider-cursor {
|
|
138
|
+
background: @error-color;
|
|
139
|
+
|
|
140
|
+
&.active {
|
|
141
|
+
background: @error-active-color;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
&:FOCUS > div.qui-slider-bar-container > div.qui-slider-bar > div.qui-slider-cursor {
|
|
149
|
+
.qui-focused-widget-error();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
&.readonly {
|
|
155
|
+
|
|
156
|
+
& > div.qui-slider-bar-container > div.qui-slider-bar {
|
|
157
|
+
border-color: @readonly-color;
|
|
158
|
+
|
|
159
|
+
& > div.qui-slider-cursor {
|
|
160
|
+
background: @foreground-color;
|
|
161
|
+
|
|
162
|
+
&.active {
|
|
163
|
+
background: @foreground-color;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
&:FOCUS > div.qui-slider-bar-container > div.qui-slider-bar > div.qui-slider-cursor {
|
|
171
|
+
.qui-focused-widget-readonly();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
&.disabled {
|
|
177
|
+
|
|
178
|
+
& > div.qui-slider-labels > span.qui-slider-label {
|
|
179
|
+
color: @disabled-color;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
& > div.qui-slider-bar-container > div.qui-slider-bar {
|
|
183
|
+
border-color: @disabled-color;
|
|
184
|
+
|
|
185
|
+
& > div.qui-slider-cursor {
|
|
186
|
+
background: @disabled-color;
|
|
187
|
+
cursor: default;
|
|
188
|
+
|
|
189
|
+
&.active {
|
|
190
|
+
background: @disabled-color;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
|
|
2
|
+
@import (reference) "../base";
|
|
3
|
+
@import (reference) "../theme";
|
|
4
|
+
@import (reference) "common";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
div.qui-updown-container {
|
|
8
|
+
white-space: nowrap;
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
border-radius: 0.2em;
|
|
11
|
+
.qui-focusable-widget();
|
|
12
|
+
|
|
13
|
+
& > input.qui-updown-input {
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 1.75em;
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
border-color: @interactive-color;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
& > div.qui-updown-button {
|
|
21
|
+
display: inline-block;
|
|
22
|
+
width: 1.75em;
|
|
23
|
+
height: 1.75em;
|
|
24
|
+
line-height: 1.75em;
|
|
25
|
+
vertical-align: top;
|
|
26
|
+
text-align: center;
|
|
27
|
+
border-width: 0;
|
|
28
|
+
|
|
29
|
+
&.down {
|
|
30
|
+
margin-left: -3.5625em;
|
|
31
|
+
border-radius: 0;
|
|
32
|
+
|
|
33
|
+
&:AFTER {
|
|
34
|
+
content: '\2013';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&.up {
|
|
40
|
+
margin-left: 0.0625em;
|
|
41
|
+
border-radius: 0 0.2em 0.2em 0;
|
|
42
|
+
|
|
43
|
+
&:AFTER {
|
|
44
|
+
content: '+';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&:FOCUS {
|
|
52
|
+
.qui-focused-widget();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&.has-error {
|
|
56
|
+
|
|
57
|
+
& > input.qui-updown-input {
|
|
58
|
+
border-color: @error-color;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
& > div.qui-updown-button {
|
|
62
|
+
background: @error-color;
|
|
63
|
+
|
|
64
|
+
&.active {
|
|
65
|
+
background: @error-active-color;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&:FOCUS {
|
|
70
|
+
.qui-focused-widget-error();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&.readonly {
|
|
76
|
+
|
|
77
|
+
& > input.qui-updown-input {
|
|
78
|
+
border-color: @readonly-color;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
& > div.qui-updown-button {
|
|
82
|
+
background: @readonly-color;
|
|
83
|
+
cursor: default;
|
|
84
|
+
|
|
85
|
+
&.active {
|
|
86
|
+
background: @readonly-color;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&:FOCUS {
|
|
92
|
+
.qui-focused-widget-readonly();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&.disabled {
|
|
98
|
+
|
|
99
|
+
& > input.qui-updown-input {
|
|
100
|
+
border-color: @disabled-color;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
& > div.qui-updown-button {
|
|
104
|
+
background: @disabled-color;
|
|
105
|
+
cursor: default;
|
|
106
|
+
|
|
107
|
+
&.active {
|
|
108
|
+
background: @disabled-color;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
@import (reference) "../base";
|
|
3
|
+
@import (reference) "../theme";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
.qui-active-indicator {
|
|
7
|
+
content: '';
|
|
8
|
+
display: block;
|
|
9
|
+
position: absolute;
|
|
10
|
+
width: 100%;
|
|
11
|
+
left: 0;
|
|
12
|
+
height: 0;
|
|
13
|
+
bottom: 0;
|
|
14
|
+
background: @interactive-color;
|
|
15
|
+
transition: height @transition-duration ease;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.qui-active-indicator-visible {
|
|
19
|
+
height: 0.25em;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
div.qui-icon-text-caption-container {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
div.qui-icon-text-caption-icon {
|
|
29
|
+
width: 1.5em;
|
|
30
|
+
height: 1.5em;
|
|
31
|
+
top: -0.05em;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
span.qui-icon-text-caption-text {
|
|
35
|
+
margin-left: 0.2em;
|
|
36
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@qtoggle/qui",
|
|
3
|
+
"description": "A JavaScript UI library with batteries included.",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Calin Crisan",
|
|
7
|
+
"email": "ccrisan@gmail.com"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"jquery": "*",
|
|
13
|
+
"jquery-mousewheel": "*",
|
|
14
|
+
"jquery-ui-dist": "*",
|
|
15
|
+
"js-logger": "*",
|
|
16
|
+
"pepjs": "*"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@babel/core": "^7",
|
|
20
|
+
"@babel/plugin-proposal-class-properties": "^7",
|
|
21
|
+
"@babel/preset-env": "^7",
|
|
22
|
+
"babel-eslint": "^10",
|
|
23
|
+
"babel-loader": "^8",
|
|
24
|
+
"css-loader": "^3",
|
|
25
|
+
"eslint": "^6",
|
|
26
|
+
"expose-loader": "^0",
|
|
27
|
+
"file-loader": "^6",
|
|
28
|
+
"glob": "^7",
|
|
29
|
+
"jsdoc": "^3",
|
|
30
|
+
"jsdoc-export-default-interop": "^0",
|
|
31
|
+
"jsdoc-typeof-plugin": "^1",
|
|
32
|
+
"less": "^3",
|
|
33
|
+
"less-loader": "^6",
|
|
34
|
+
"mini-css-extract-plugin": "^0",
|
|
35
|
+
"optimize-css-assets-webpack-plugin": "^5",
|
|
36
|
+
"string-replace-loader": "^2",
|
|
37
|
+
"terser-webpack-plugin": "^3",
|
|
38
|
+
"webpack": "^4",
|
|
39
|
+
"webpack-cli": "^3",
|
|
40
|
+
"webpack-fix-style-only-entries": "^0",
|
|
41
|
+
"webpack-inject-plugin": "^1",
|
|
42
|
+
"webpack-shell-plugin": "^0"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"postinstall": "scripts/postinstall.sh"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/pyproject.toml
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "qui-server"
|
|
3
|
+
version = "0.0.0"
|
|
4
|
+
description = "A fully fledged qToggle implementation written in Python"
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Calin Crisan", email = "ccrisan@gmail.com"},
|
|
7
|
+
]
|
|
8
|
+
requires-python = "==3.10.*"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "Apache 2.0"}
|
|
11
|
+
dependencies = [
|
|
12
|
+
"jinja2",
|
|
13
|
+
"tornado",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[tool.setuptools.packages.find]
|
|
17
|
+
include = [
|
|
18
|
+
"qui*",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[tool.setuptools.package-data]
|
|
22
|
+
qui = [
|
|
23
|
+
"templates/**",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[tool.uv]
|
|
27
|
+
package = true
|
|
28
|
+
|
|
29
|
+
[tool.ruff]
|
|
30
|
+
line-length = 120
|
|
31
|
+
target-version = "py310"
|
|
32
|
+
lint.extend-select = ["I", "RUF022"]
|
|
33
|
+
lint.isort.lines-after-imports = 2
|
|
34
|
+
lint.isort.lines-between-types = 1
|
|
35
|
+
lint.isort.force-wrap-aliases = true
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
dev = [
|
|
39
|
+
"ruff",
|
|
40
|
+
"pre-commit",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[tool.mypy]
|
|
44
|
+
explicit_package_bases = true
|
|
45
|
+
ignore_missing_imports = true
|
package/qui/__init__.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import logging
|
|
3
|
+
import re
|
|
4
|
+
import secrets
|
|
5
|
+
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from . import settings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def configure(
|
|
15
|
+
*,
|
|
16
|
+
name: str,
|
|
17
|
+
display_name: str,
|
|
18
|
+
display_short_name: str | None = None,
|
|
19
|
+
description: str,
|
|
20
|
+
version: str,
|
|
21
|
+
debug: bool,
|
|
22
|
+
theme_color: str | None = None,
|
|
23
|
+
background_color: str | None = None,
|
|
24
|
+
frontend_dir: str | None = None,
|
|
25
|
+
frontend_url_prefix: str | None = None,
|
|
26
|
+
static_url: str | None = None,
|
|
27
|
+
package_name: str | None = None,
|
|
28
|
+
enable_pwa: bool | None = None,
|
|
29
|
+
extra_context: dict[str, Any] | None = None,
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Configure QUI on the server side.
|
|
32
|
+
|
|
33
|
+
:param name: project name, normally lowercase, no spaces, e.g. ``my-project``
|
|
34
|
+
:param display_name: project display name, e.g. ``My Nice And Shiny Project``
|
|
35
|
+
:param display_short_name: optional project display short name, e.g. ``My Project``
|
|
36
|
+
:param description: project description, e.g. ``A project that does stuff``
|
|
37
|
+
:param version: project version
|
|
38
|
+
:param debug: indicates whether frontend runs in debug mode or not
|
|
39
|
+
:param theme_color: optionally overrides default theme (accent) color
|
|
40
|
+
:param background_color: overrides default background color
|
|
41
|
+
:param frontend_dir: overrides default frontend directory, relative to project root package (defaults to
|
|
42
|
+
``frontend``)
|
|
43
|
+
:param frontend_url_prefix: overrides default frontend URL prefix (defaults to ``frontend``)
|
|
44
|
+
:param static_url: overrides default URL where static files are served (defaults to
|
|
45
|
+
``{frontend_url_prefix}/static``)
|
|
46
|
+
:param package_name: sets the root project package name; by default, the ``name`` parameter is used after removing
|
|
47
|
+
non-alpha-numeric-or-underscore characters
|
|
48
|
+
:param enable_pwa: enables or disables PWA support (enabled by default)
|
|
49
|
+
:param extra_context: specifies extra context to be supplied when rendering templates
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
settings.name = name
|
|
53
|
+
settings.display_name = display_name
|
|
54
|
+
settings.description = description
|
|
55
|
+
settings.version = version
|
|
56
|
+
settings.debug = debug
|
|
57
|
+
|
|
58
|
+
if display_short_name is not None:
|
|
59
|
+
settings.display_short_name = display_short_name
|
|
60
|
+
|
|
61
|
+
if theme_color is not None:
|
|
62
|
+
settings.theme_color = theme_color
|
|
63
|
+
|
|
64
|
+
if background_color is not None:
|
|
65
|
+
settings.background_color = background_color
|
|
66
|
+
|
|
67
|
+
if frontend_dir is not None:
|
|
68
|
+
settings.frontend_dir = frontend_dir
|
|
69
|
+
|
|
70
|
+
if frontend_url_prefix is not None:
|
|
71
|
+
settings.frontend_url_prefix = frontend_url_prefix
|
|
72
|
+
|
|
73
|
+
if static_url is not None:
|
|
74
|
+
settings.static_url = static_url
|
|
75
|
+
|
|
76
|
+
if package_name is not None:
|
|
77
|
+
settings.package_name = package_name
|
|
78
|
+
|
|
79
|
+
if enable_pwa is not None:
|
|
80
|
+
settings.enable_pwa = enable_pwa
|
|
81
|
+
|
|
82
|
+
if extra_context is not None:
|
|
83
|
+
settings.extra_context = extra_context
|
|
84
|
+
|
|
85
|
+
# Static URL may (and normally does) depend on frontend URL prefix
|
|
86
|
+
settings.static_url = settings.static_url.format(frontend_url_prefix=settings.frontend_url_prefix)
|
|
87
|
+
|
|
88
|
+
# Project package defaults to app (project) name
|
|
89
|
+
if not settings.package_name:
|
|
90
|
+
settings.package_name = re.sub(r"[^a-zA-Z_0-9]", "", settings.name)
|
|
91
|
+
|
|
92
|
+
if settings.debug:
|
|
93
|
+
settings.build_hash = secrets.token_hex()[:16]
|
|
94
|
+
|
|
95
|
+
else:
|
|
96
|
+
settings.build_hash = hashlib.sha256(version.encode()).hexdigest()[:16]
|
|
97
|
+
|
|
98
|
+
logger.debug('using name = "%s"', settings.name)
|
|
99
|
+
logger.debug('using display_name = "%s"', settings.display_name)
|
|
100
|
+
logger.debug('using description = "%s"', settings.description)
|
|
101
|
+
logger.debug('using version = "%s"', settings.version)
|
|
102
|
+
logger.debug("using debug = %s", str(settings.debug).lower())
|
|
103
|
+
logger.debug('using theme_color = "%s"', settings.theme_color)
|
|
104
|
+
logger.debug('using background_color = "%s"', settings.background_color)
|
|
105
|
+
logger.debug('using frontend_dir = "%s"', settings.frontend_dir)
|
|
106
|
+
logger.debug('using frontend_url_prefix = "%s"', settings.frontend_url_prefix)
|
|
107
|
+
logger.debug('using static_url = "%s"', settings.static_url)
|
|
108
|
+
logger.debug('using package_name = "%s"', settings.package_name)
|
|
109
|
+
logger.debug("using enable_pwa = %s", str(settings.enable_pwa).lower())
|
|
110
|
+
logger.debug('using build_hash = "%s"', settings.build_hash)
|
package/qui/constants.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
BASE_PREFIX_HEADER = "X-Forwarded-Path"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from urllib.parse import quote_plus
|
|
6
|
+
|
|
7
|
+
from jinja2 import (
|
|
8
|
+
ChoiceLoader,
|
|
9
|
+
Environment,
|
|
10
|
+
FileSystemLoader,
|
|
11
|
+
PackageLoader,
|
|
12
|
+
select_autoescape,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from . import settings
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
_env: Environment | None = None
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class NamespaceLoader(FileSystemLoader):
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
namespace_name: str,
|
|
27
|
+
path: str | list[str] = "templates",
|
|
28
|
+
encoding: str = "utf-8",
|
|
29
|
+
followlinks: bool = False,
|
|
30
|
+
) -> None:
|
|
31
|
+
if isinstance(path, str):
|
|
32
|
+
path = [path]
|
|
33
|
+
|
|
34
|
+
namespace = importlib.import_module(namespace_name)
|
|
35
|
+
namespace_path_list = list(namespace.__path__)
|
|
36
|
+
searchpath = []
|
|
37
|
+
for namespace_path in namespace_path_list:
|
|
38
|
+
searchpath += [os.path.join(namespace_path, p) for p in path]
|
|
39
|
+
|
|
40
|
+
super().__init__(searchpath=searchpath, encoding=encoding, followlinks=followlinks)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def urlquote(s: str | bytes) -> str | bytes:
|
|
44
|
+
if s:
|
|
45
|
+
return quote_plus(s)
|
|
46
|
+
|
|
47
|
+
return s
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_env() -> Environment:
|
|
51
|
+
global _env
|
|
52
|
+
|
|
53
|
+
if _env is None:
|
|
54
|
+
logger.debug("creating Jinja2 template environment")
|
|
55
|
+
|
|
56
|
+
app_loader = NamespaceLoader(
|
|
57
|
+
settings.package_name,
|
|
58
|
+
[
|
|
59
|
+
f"{settings.frontend_dir}/templates",
|
|
60
|
+
f"{settings.frontend_dir}/dist/templates",
|
|
61
|
+
],
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
qui_loader = PackageLoader("qui")
|
|
65
|
+
|
|
66
|
+
loader = ChoiceLoader([qui_loader, app_loader])
|
|
67
|
+
|
|
68
|
+
_env = Environment(loader=loader, autoescape=select_autoescape(), enable_async=True)
|
|
69
|
+
_env.filters["urlquote"] = urlquote
|
|
70
|
+
|
|
71
|
+
return _env
|