jsl-ui 9.28.7 → 10.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/docs/AutoSuggestComponent.md +17 -0
- package/docs/ButtonComponent.md +14 -0
- package/docs/CheckBoxComponent.md +12 -0
- package/docs/DateComponent.md +12 -0
- package/docs/DateRangeComponent.md +13 -0
- package/docs/DateTimeComponent.md +13 -0
- package/docs/DialogComponent.md +15 -0
- package/docs/ExpanderComponent.md +13 -0
- package/docs/FormComponent.md +15 -0
- package/docs/FormFieldComponent.md +15 -0
- package/docs/GridComponent.md +19 -0
- package/docs/InputComponent.md +15 -0
- package/docs/IntervalComponent.md +13 -0
- package/docs/LoadingComponent.md +12 -0
- package/docs/NavigationComponent.md +17 -0
- package/docs/Notification.md +14 -0
- package/docs/NotificationComponent.md +13 -0
- package/docs/NumberComponent.md +12 -0
- package/docs/OverlayComponent.md +12 -0
- package/docs/ProgressComponent.md +12 -0
- package/docs/README.md +24 -0
- package/docs/RibbonMenuComponent.md +14 -0
- package/docs/SelectComponent.md +15 -0
- package/docs/SplitterComponent.md +14 -0
- package/docs/StackPanelComponent.md +13 -0
- package/docs/TabsComponent.md +16 -0
- package/docs/TimeComponent.md +13 -0
- package/docs/TreeViewComponent.md +16 -0
- package/examples/showcase/checks-and-expanders.ts +163 -0
- package/examples/showcase/cultures.ts +39 -0
- package/examples/showcase/dates.ts +182 -0
- package/examples/showcase/dialogs.ts +184 -0
- package/examples/showcase/feedback-and-navigation.ts +174 -0
- package/examples/showcase/fields.ts +178 -0
- package/examples/showcase/fonts/Jost-Variable.ttf +0 -0
- package/examples/showcase/fonts/OFL-Jost.txt +93 -0
- package/examples/showcase/grids.ts +150 -0
- package/examples/showcase/index.html +60 -0
- package/examples/showcase/layout-and-navigation.ts +47 -0
- package/examples/showcase/nivona.css +98 -0
- package/examples/showcase/selects.ts +158 -0
- package/examples/showcase/showcase.css +231 -0
- package/examples/showcase/showcase.ts +214 -0
- package/examples/showcase/tabs.ts +161 -0
- package/examples/showcase/themes.css +83 -0
- package/examples/showcase/themes.ts +54 -0
- package/lib/components/IntervalComponent.d.ts +5 -0
- package/lib/components/IntervalComponent.js +29 -13
- package/lib/components/auto-suggest/AutoSuggestComponent.d.ts +11 -9
- package/lib/components/auto-suggest/AutoSuggestComponent.js +25 -38
- package/lib/components/button/ButtonComponent.d.ts +30 -1
- package/lib/components/button/ButtonComponent.js +85 -4
- package/lib/components/checkbox/CheckBoxComponent.d.ts +11 -1
- package/lib/components/checkbox/CheckBoxComponent.js +66 -56
- package/lib/components/checkbox/CheckBoxStyle.scss +72 -85
- package/lib/components/date/DateComponent.d.ts +10 -0
- package/lib/components/date/DateComponent.js +92 -44
- package/lib/components/date-range/DateRangeComponent.d.ts +14 -3
- package/lib/components/date-range/DateRangeComponent.js +96 -86
- package/lib/components/date-range/DateRangeStyle.scss +35 -11
- package/lib/components/date-time/DateTimeComponent.d.ts +8 -0
- package/lib/components/date-time/DateTimeComponent.js +64 -23
- package/lib/components/date-time/DateTimeStyle.scss +10 -7
- package/lib/components/dialog/DialogComponent.d.ts +21 -7
- package/lib/components/dialog/DialogComponent.js +179 -122
- package/lib/components/expander/ExpanderComponent.d.ts +15 -1
- package/lib/components/expander/ExpanderComponent.js +85 -64
- package/lib/components/expander/ExpanderStyle.scss +61 -47
- package/lib/components/form-field/FormFieldComponent.d.ts +45 -15
- package/lib/components/form-field/FormFieldComponent.js +249 -96
- package/lib/components/form-field/FormFieldStyle.scss +36 -87
- package/lib/components/form-field/create-control.d.ts +7 -0
- package/lib/components/form-field/create-control.js +48 -0
- package/lib/components/input/InputComponent.d.ts +18 -1
- package/lib/components/input/InputComponent.js +68 -93
- package/lib/components/loading/LoadingComponent.d.ts +9 -2
- package/lib/components/loading/LoadingComponent.js +13 -12
- package/lib/components/loading/LoadingStyle.css +19 -29
- package/lib/components/navigation/NavigationComponent.d.ts +34 -10
- package/lib/components/navigation/NavigationComponent.js +261 -33
- package/lib/components/navigation/NavigationStyle.scss +62 -226
- package/lib/components/notification/Notification.d.ts +37 -4
- package/lib/components/notification/Notification.js +160 -41
- package/lib/components/notification/Notification.scss +103 -19
- package/lib/components/number/NumberComponent.d.ts +16 -2
- package/lib/components/number/NumberComponent.js +54 -53
- package/lib/components/overlay/OverlayComponent.d.ts +13 -7
- package/lib/components/overlay/OverlayComponent.js +46 -114
- package/lib/components/overlay/overlay.css +18 -57
- package/lib/components/progress/ProgressComponent.d.ts +1 -0
- package/lib/components/progress/ProgressComponent.js +6 -6
- package/lib/components/progress/ProgressStyle.scss +5 -15
- package/lib/components/ribbon-menu/RibbonMenuComponent.js +2 -2
- package/lib/components/ribbon-menu/RibbonMenuStyle.scss +6 -76
- package/lib/components/select/SelectComponent.d.ts +33 -3
- package/lib/components/select/SelectComponent.js +312 -278
- package/lib/components/select/SelectDDAreaComponent.d.ts +13 -7
- package/lib/components/select/SelectDDAreaComponent.js +215 -256
- package/lib/components/select/SelectStyle.scss +204 -186
- package/lib/components/slider/nouislider.css +40 -54
- package/lib/components/stack-panel/SplitterComponent.d.ts +19 -3
- package/lib/components/stack-panel/SplitterComponent.js +94 -111
- package/lib/components/stack-panel/SplitterStyle.scss +9 -45
- package/lib/components/stack-panel/StackPanelComponent.js +3 -3
- package/lib/components/stack-panel/StackPanelStyle.scss +10 -52
- package/lib/components/tabs/TabsComponent.d.ts +17 -1
- package/lib/components/tabs/TabsComponent.js +247 -123
- package/lib/components/tabs/TabsStyle.scss +138 -75
- package/lib/components/time/TimeComponent.d.ts +5 -0
- package/lib/components/time/TimeComponent.js +61 -69
- package/lib/components/time/TimeComponent.scss +4 -4
- package/lib/components/tree-view/TreeViewComponent.d.ts +10 -4
- package/lib/components/tree-view/TreeViewComponent.js +65 -32
- package/lib/components/tree-view/TreeViewStyle.scss +12 -96
- package/lib/core/date.d.ts +2 -0
- package/lib/core/date.js +6 -0
- package/lib/core/jq.js +11 -8
- package/lib/grid/slick-default-theme.css +107 -31
- package/lib/grid/slick.creator.js +23 -5
- package/lib/grid/slick.formatters.js +4 -3
- package/lib/grid/slick.grid.css +38 -26
- package/lib/grid/slick.grid.d.ts +1 -0
- package/lib/grid/slick.grid.js +2 -3
- package/lib/grid.css +3413 -454
- package/lib/index.css +2500 -1031
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/interaction/moveable.d.ts +1 -0
- package/lib/interaction/moveable.js +8 -0
- package/lib/interaction/resizable.d.ts +1 -0
- package/lib/interaction/resizable.js +9 -0
- package/lib/ui/auto.suggest.css +31 -14
- package/lib/ui/auto.suggest.d.ts +1 -0
- package/lib/ui/auto.suggest.js +88 -18
- package/lib/ui/base.css +2 -48
- package/lib/ui/button.css +134 -0
- package/lib/ui/date-input.css +11 -0
- package/lib/ui/date.picker/css/tiny-date-picker.css +124 -325
- package/lib/ui/date.picker/date-picker-options.js +4 -3
- package/lib/ui/date.picker/lib/date-manip.js +9 -0
- package/lib/ui/date.picker/mode/base-mode.d.ts +2 -1
- package/lib/ui/date.picker/mode/base-mode.js +112 -22
- package/lib/ui/date.picker/mode/dropdown-mode.d.ts +2 -4
- package/lib/ui/date.picker/mode/dropdown-mode.js +29 -42
- package/lib/ui/date.picker/mode/index.d.ts +2 -1
- package/lib/ui/date.picker/mode/modal-mode.d.ts +2 -1
- package/lib/ui/date.picker/mode/modal-mode.js +4 -2
- package/lib/ui/date.picker/mode/permanent-mode.d.ts +2 -1
- package/lib/ui/date.picker/views/day-picker.js +24 -15
- package/lib/ui/date.picker/views/month-picker.js +1 -1
- package/lib/ui/date.picker/views/year-picker.js +3 -2
- package/lib/ui/date.picker.d.ts +2 -1
- package/lib/ui/dialog.css +144 -108
- package/lib/ui/dialog.d.ts +19 -1
- package/lib/ui/dialog.js +178 -60
- package/lib/ui/input.css +35 -0
- package/lib/ui/number.input.js +50 -37
- package/lib/ui/theme.css +28 -0
- package/package.json +12 -8
- package/lib/components/drop-down/DropDownComponent.d.ts +0 -27
- package/lib/components/drop-down/DropDownComponent.js +0 -60
- package/lib/components/expander/OldExpanderStyle.scss +0 -37
- package/lib/ui/drop.down.d.ts +0 -52
- package/lib/ui/drop.down.js +0 -2112
|
@@ -1,65 +1,184 @@
|
|
|
1
1
|
import "./Notification.scss";
|
|
2
2
|
import { JSLRender } from "jsl-render";
|
|
3
3
|
import { helper } from "../../core/helper";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/** The same surface can be rendered inline or hosted by Notification.show(). */
|
|
5
|
+
export class NotificationComponent {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.options = options;
|
|
8
|
+
this.State = { closed: false };
|
|
9
|
+
this.id = helper.newDomGuid();
|
|
10
|
+
this.interactions = new Set();
|
|
11
|
+
}
|
|
12
|
+
onInit(renderer) { this.renderer = renderer; }
|
|
13
|
+
onCreate(node) { this.dom = node.dom; this.updateProgress(); }
|
|
14
|
+
onRemove() { var _a; (_a = this.progressAnimation) === null || _a === void 0 ? void 0 : _a.cancel(); this.dom = undefined; }
|
|
15
|
+
/** The notification host keeps the visual countdown synchronized with dismissal. */
|
|
16
|
+
setCountdown(remaining, paused) {
|
|
17
|
+
this.countdown = { remaining, paused, updatedAt: Date.now() };
|
|
18
|
+
this.updateProgress();
|
|
19
|
+
}
|
|
20
|
+
updateProgress() {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
(_a = this.progressAnimation) === null || _a === void 0 ? void 0 : _a.cancel();
|
|
23
|
+
const bar = (_b = this.dom) === null || _b === void 0 ? void 0 : _b.querySelector(".jsl-notification-progress-fill");
|
|
24
|
+
if (!bar || !this.countdown) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const remaining = Math.max(0, this.countdown.remaining - (this.countdown.paused ? 0 : Date.now() - this.countdown.updatedAt));
|
|
28
|
+
const fraction = remaining / this.options.timeOut;
|
|
29
|
+
bar.style.transform = "scaleX(" + fraction + ")";
|
|
30
|
+
if (!this.countdown.paused && remaining > 0) {
|
|
31
|
+
this.progressAnimation = bar.animate([
|
|
32
|
+
{ transform: "scaleX(" + fraction + ")" }, { transform: "scaleX(0)" }
|
|
33
|
+
], { duration: remaining, fill: "forwards", easing: "linear" });
|
|
8
34
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
35
|
+
}
|
|
36
|
+
render() {
|
|
37
|
+
var _a, _b, _c;
|
|
38
|
+
const variant = (_a = this.options.variant) !== null && _a !== void 0 ? _a : "default";
|
|
39
|
+
const symbols = { default: "i", info: "i", success: "✓", warning: "!", error: "!" };
|
|
40
|
+
return {
|
|
41
|
+
tag: "div", attr: {
|
|
42
|
+
id: this.id, hidden: this.State.closed ? "hidden" : undefined,
|
|
43
|
+
class: "jsl-notification jsl-notification--" + variant + " " + ((_b = this.options.class) !== null && _b !== void 0 ? _b : ""),
|
|
44
|
+
style: this.options.style, role: variant === "error" || variant === "warning" ? "alert" : "status",
|
|
45
|
+
"aria-atomic": "true",
|
|
46
|
+
tabindex: this.options.onClick ? "0" : undefined,
|
|
47
|
+
click: () => { this.activate(); return false; },
|
|
48
|
+
keydown: (event) => {
|
|
49
|
+
if (event.target === event.currentTarget && (event.key === "Enter" || event.key === " ")) {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
event.stopPropagation();
|
|
52
|
+
this.activate();
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
},
|
|
56
|
+
mouseenter: () => { this.pause("pointer", true); return false; },
|
|
57
|
+
mouseleave: () => { this.pause("pointer", false); return false; },
|
|
58
|
+
focusin: () => { this.pause("focus", true); return false; },
|
|
59
|
+
focusout: (event) => {
|
|
60
|
+
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
61
|
+
this.pause("focus", false);
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}, children: [
|
|
66
|
+
{ tag: "span", content: symbols[variant], attr: { class: "jsl-notification-icon", "aria-hidden": "true" } },
|
|
67
|
+
{ tag: "div", attr: { class: "jsl-notification-copy" }, children: [
|
|
68
|
+
{ tag: "div", content: this.options.title, attr: { class: "jsl-notification-title", hidden: this.options.title ? undefined : "hidden" } },
|
|
69
|
+
typeof this.options.content === "string" ? { tag: "div", content: this.options.content } : this.options.content
|
|
70
|
+
] },
|
|
71
|
+
{ tag: "button", attr: {
|
|
72
|
+
type: "button", class: "jsl-notification-close",
|
|
73
|
+
hidden: this.options.showCloseButton === false ? "hidden" : undefined,
|
|
74
|
+
"aria-label": (_c = this.options.closeButtonLabel) !== null && _c !== void 0 ? _c : "Dismiss notification",
|
|
75
|
+
click: (event) => { event.stopPropagation(); this.dismiss(); return false; }
|
|
76
|
+
}, children: [{ tag: "span", content: "×", attr: { "aria-hidden": "true" } }] },
|
|
77
|
+
...(this.countdown ? [{ tag: "div", attr: { class: "jsl-notification-progress", "aria-hidden": "true" }, children: [
|
|
78
|
+
{ tag: "span", attr: { class: "jsl-notification-progress-fill" } }
|
|
79
|
+
] }] : [])
|
|
17
80
|
]
|
|
18
81
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
82
|
+
}
|
|
83
|
+
dismiss() {
|
|
84
|
+
var _a, _b, _c;
|
|
85
|
+
if (this.State.closed) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.State.closed = true;
|
|
89
|
+
(_b = (_a = this.options).onClose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
90
|
+
(_c = this.renderer) === null || _c === void 0 ? void 0 : _c.refresh();
|
|
91
|
+
}
|
|
92
|
+
activate() {
|
|
93
|
+
var _a, _b, _c, _d;
|
|
94
|
+
(_b = (_a = this.options).onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
95
|
+
if ((_c = this.options.closeOnClick) !== null && _c !== void 0 ? _c : true) {
|
|
96
|
+
this.dismiss();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
(_d = this.renderer) === null || _d === void 0 ? void 0 : _d.refresh();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
pause(reason, paused) {
|
|
103
|
+
var _a;
|
|
104
|
+
const wasPaused = this.interactions.size > 0;
|
|
105
|
+
if (paused) {
|
|
106
|
+
this.interactions.add(reason);
|
|
30
107
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
108
|
+
else {
|
|
109
|
+
this.interactions.delete(reason);
|
|
110
|
+
}
|
|
111
|
+
if (wasPaused !== (this.interactions.size > 0)) {
|
|
112
|
+
(_a = this.onInteractionChange) === null || _a === void 0 ? void 0 : _a.call(this, this.interactions.size > 0);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export class Notification {
|
|
117
|
+
static show(options) {
|
|
118
|
+
var _a, _b;
|
|
119
|
+
if (!((_a = Notification.container) === null || _a === void 0 ? void 0 : _a.isConnected)) {
|
|
120
|
+
Notification.createContainer();
|
|
121
|
+
}
|
|
122
|
+
const component = new NotificationComponent({
|
|
123
|
+
...options, onClose: () => {
|
|
124
|
+
var _a;
|
|
125
|
+
Notification.remove(component.id);
|
|
126
|
+
(_a = options.onClose) === null || _a === void 0 ? void 0 : _a.call(options);
|
|
35
127
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
128
|
+
});
|
|
129
|
+
const entry = { component, remaining: Math.max(0, (_b = options.timeOut) !== null && _b !== void 0 ? _b : 0), started: 0 };
|
|
130
|
+
Notification.entries.set(component.id, entry);
|
|
131
|
+
component.onInteractionChange = paused => {
|
|
132
|
+
if (!Notification.entries.has(component.id) || !entry.remaining) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (paused) {
|
|
136
|
+
if (entry.timer != null) {
|
|
137
|
+
clearTimeout(entry.timer);
|
|
138
|
+
entry.timer = undefined;
|
|
139
|
+
entry.remaining = Math.max(1, entry.remaining - (Date.now() - entry.started));
|
|
140
|
+
component.setCountdown(entry.remaining, true);
|
|
40
141
|
}
|
|
41
142
|
}
|
|
143
|
+
else {
|
|
144
|
+
Notification.schedule(entry);
|
|
145
|
+
}
|
|
42
146
|
};
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
static clearNotification(id) {
|
|
46
|
-
Notification.containerVNode.children = Notification.containerVNode.children.filter((x) => { var _a; return ((_a = x.attr) === null || _a === void 0 ? void 0 : _a.id) !== id; });
|
|
147
|
+
Notification.containerVNode.children.push(component);
|
|
47
148
|
Notification.renderer.refresh();
|
|
149
|
+
Notification.schedule(entry);
|
|
150
|
+
return component.id;
|
|
48
151
|
}
|
|
49
|
-
static
|
|
50
|
-
|
|
51
|
-
|
|
152
|
+
static clearNotification(id) { var _a; (_a = Notification.entries.get(id)) === null || _a === void 0 ? void 0 : _a.component.dismiss(); }
|
|
153
|
+
static clearAll() { [...Notification.entries.values()].forEach(entry => entry.component.dismiss()); }
|
|
154
|
+
static schedule(entry) {
|
|
155
|
+
if (entry.timer != null || entry.remaining <= 0) {
|
|
156
|
+
return;
|
|
52
157
|
}
|
|
53
|
-
|
|
54
|
-
|
|
158
|
+
entry.started = Date.now();
|
|
159
|
+
entry.component.setCountdown(entry.remaining, false);
|
|
160
|
+
entry.timer = setTimeout(() => { entry.timer = undefined; entry.component.dismiss(); }, entry.remaining);
|
|
161
|
+
}
|
|
162
|
+
static remove(id) {
|
|
163
|
+
const entry = Notification.entries.get(id);
|
|
164
|
+
if (!entry) {
|
|
165
|
+
return;
|
|
55
166
|
}
|
|
167
|
+
clearTimeout(entry.timer);
|
|
168
|
+
Notification.entries.delete(id);
|
|
169
|
+
Notification.containerVNode.children = Notification.containerVNode.children.filter(child => child !== entry.component);
|
|
170
|
+
Notification.renderer.refresh();
|
|
56
171
|
}
|
|
57
172
|
static createContainer() {
|
|
173
|
+
// An application may replace its body while notifications exist.
|
|
174
|
+
[...Notification.entries.values()].forEach(entry => clearTimeout(entry.timer));
|
|
175
|
+
Notification.entries.clear();
|
|
58
176
|
Notification.container = document.createElement("div");
|
|
59
|
-
document.body.appendChild(Notification.container);
|
|
60
177
|
Notification.container.className = "jsl-notification-container";
|
|
178
|
+
document.body.appendChild(Notification.container);
|
|
61
179
|
Notification.containerVNode = { tag: "div", children: [] };
|
|
62
180
|
Notification.renderer = new JSLRender(Notification.container, false);
|
|
63
181
|
Notification.renderer.render(Notification.containerVNode);
|
|
64
182
|
}
|
|
65
183
|
}
|
|
184
|
+
Notification.entries = new Map();
|
|
@@ -1,19 +1,103 @@
|
|
|
1
|
-
.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
@import "../../ui/theme.css";
|
|
2
|
+
|
|
3
|
+
.jsl-notification-container {
|
|
4
|
+
position: fixed;
|
|
5
|
+
top: 0;
|
|
6
|
+
right: 0;
|
|
7
|
+
width: 25rem;
|
|
8
|
+
max-width: 100vw;
|
|
9
|
+
max-height: 100dvh;
|
|
10
|
+
overflow-y: auto;
|
|
11
|
+
z-index: 3020;
|
|
12
|
+
// Leave space for individual shadows so scrolling doesn't crop them into a rectangle.
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
padding: 1rem;
|
|
15
|
+
background: transparent;
|
|
16
|
+
border: 0;
|
|
17
|
+
border-radius: 1.75rem;
|
|
18
|
+
box-shadow: none;
|
|
19
|
+
pointer-events: none;
|
|
20
|
+
scrollbar-width: thin;
|
|
21
|
+
}
|
|
22
|
+
.jsl-notification-container > div { display: flex; flex-direction: column; gap: .75rem; }
|
|
23
|
+
.jsl-notification {
|
|
24
|
+
position: relative;
|
|
25
|
+
--jsl-notification-tone: var(--jsl-color-text-secondary);
|
|
26
|
+
display: grid;
|
|
27
|
+
grid-template-columns: 1.25rem minmax(0, 1fr) auto;
|
|
28
|
+
align-items: start;
|
|
29
|
+
gap: .75rem;
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
width: 100%;
|
|
32
|
+
padding: 1rem;
|
|
33
|
+
border: 1px solid var(--jsl-color-border);
|
|
34
|
+
border-radius: .75rem;
|
|
35
|
+
background: var(--jsl-color-surface);
|
|
36
|
+
color: var(--jsl-color-text);
|
|
37
|
+
font: inherit;
|
|
38
|
+
font-size: .8125rem;
|
|
39
|
+
line-height: 1.5;
|
|
40
|
+
box-shadow: 0 8px 24px rgba(0,0,0,.1), 0 1px 4px rgba(0,0,0,.04);
|
|
41
|
+
pointer-events: auto;
|
|
42
|
+
animation: jsl-notification-appear .16s ease-out;
|
|
43
|
+
}
|
|
44
|
+
.jsl-notification[hidden] { display: none; }
|
|
45
|
+
.jsl-notification--info { --jsl-notification-tone: var(--jsl-color-info); }
|
|
46
|
+
.jsl-notification--success { --jsl-notification-tone: var(--jsl-color-success); }
|
|
47
|
+
.jsl-notification--warning { --jsl-notification-tone: var(--jsl-color-warning); }
|
|
48
|
+
.jsl-notification--error { --jsl-notification-tone: var(--jsl-color-danger); }
|
|
49
|
+
.jsl-notification-icon {
|
|
50
|
+
display: grid;
|
|
51
|
+
place-items: center;
|
|
52
|
+
box-sizing: border-box;
|
|
53
|
+
width: 1.125rem;
|
|
54
|
+
height: 1.125rem;
|
|
55
|
+
margin-top: .125rem;
|
|
56
|
+
border: 1.5px solid currentColor;
|
|
57
|
+
border-radius: 50%;
|
|
58
|
+
color: var(--jsl-notification-tone);
|
|
59
|
+
font-size: .6875rem;
|
|
60
|
+
font-weight: 700;
|
|
61
|
+
line-height: 1;
|
|
62
|
+
}
|
|
63
|
+
.jsl-notification--success .jsl-notification-icon { font-size: .75rem; }
|
|
64
|
+
.jsl-notification-copy { min-width: 0; overflow-wrap: anywhere; }
|
|
65
|
+
.jsl-notification-title { margin-bottom: .25rem; font-weight: 600; color: var(--jsl-color-text); }
|
|
66
|
+
.jsl-notification-title[hidden] { display: none; }
|
|
67
|
+
.jsl-notification-close {
|
|
68
|
+
appearance: none;
|
|
69
|
+
display: grid;
|
|
70
|
+
place-items: center;
|
|
71
|
+
width: 1.5rem;
|
|
72
|
+
height: 1.5rem;
|
|
73
|
+
margin: -.125rem -.25rem 0 0;
|
|
74
|
+
padding: 0;
|
|
75
|
+
border: 0;
|
|
76
|
+
border-radius: .25rem;
|
|
77
|
+
background: transparent;
|
|
78
|
+
color: var(--jsl-color-text-muted);
|
|
79
|
+
font: inherit;
|
|
80
|
+
font-size: 1.125rem;
|
|
81
|
+
line-height: 1;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
}
|
|
84
|
+
.jsl-notification-close[hidden] { display: none; }
|
|
85
|
+
.jsl-notification-progress {
|
|
86
|
+
position: absolute;
|
|
87
|
+
inset: auto 1rem .375rem;
|
|
88
|
+
height: 3px;
|
|
89
|
+
border-radius: 999px;
|
|
90
|
+
overflow: hidden;
|
|
91
|
+
background: var(--jsl-color-border-subtle);
|
|
92
|
+
pointer-events: none;
|
|
93
|
+
}
|
|
94
|
+
.jsl-notification-progress-fill {
|
|
95
|
+
display: block;
|
|
96
|
+
height: 100%;
|
|
97
|
+
background: var(--jsl-color-accent);
|
|
98
|
+
transform-origin: left;
|
|
99
|
+
}
|
|
100
|
+
.jsl-notification-close:hover { background: var(--jsl-color-surface-hover); color: var(--jsl-color-text); }
|
|
101
|
+
.jsl-notification-close:focus-visible, .jsl-notification:focus-visible { outline: 2px solid var(--jsl-color-focus); outline-offset: 2px; }
|
|
102
|
+
@keyframes jsl-notification-appear { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
|
|
103
|
+
@media (prefers-reduced-motion: reduce) { .jsl-notification { animation: none; } }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../../ui/input.css";
|
|
2
|
+
import { IJSLComponent, IJSLVNode, JSLRender } from "jsl-render";
|
|
2
3
|
import { INumberInputOptions } from "../../ui/number.input";
|
|
3
4
|
import { EventHandler } from "../../interaction/eventhandler";
|
|
4
5
|
import { IDataConverter } from "../../interaction/dataconverter";
|
|
@@ -6,21 +7,34 @@ export interface INumberComponentOptions<T = any> extends INumberInputOptions {
|
|
|
6
7
|
id?: string;
|
|
7
8
|
class?: string;
|
|
8
9
|
style?: string;
|
|
9
|
-
placeholder?: string;
|
|
10
|
+
placeholder?: boolean | string;
|
|
10
11
|
bindTo?: T;
|
|
11
12
|
bindMode?: "toModel" | "fromModel" | "both";
|
|
12
13
|
property?: keyof T;
|
|
13
14
|
converter?: IDataConverter<any, number>;
|
|
15
|
+
unstyled?: boolean;
|
|
16
|
+
ariaLabel?: string;
|
|
17
|
+
readOnly?: boolean;
|
|
14
18
|
}
|
|
15
19
|
export declare class NumberComponent<T = any> implements IJSLComponent {
|
|
16
20
|
private currentDom;
|
|
17
21
|
private id;
|
|
18
22
|
private options;
|
|
23
|
+
private modelValue;
|
|
24
|
+
private renderer;
|
|
19
25
|
constructor(options: INumberComponentOptions<T>);
|
|
20
26
|
get onChange(): EventHandler<number>;
|
|
21
27
|
render(): IJSLVNode;
|
|
22
28
|
getValue(): string;
|
|
23
29
|
getValueAsNumber(): number;
|
|
30
|
+
isValid(): boolean;
|
|
31
|
+
/** Updates the input and writable binding without raising onChange. */
|
|
24
32
|
setValue(value: number): void;
|
|
33
|
+
focus(): void;
|
|
34
|
+
onInit(renderer: JSLRender): void;
|
|
25
35
|
onCreate(node: IJSLVNode): void;
|
|
36
|
+
onRemove(): void;
|
|
37
|
+
private hasBinding;
|
|
38
|
+
private readModel;
|
|
39
|
+
private writeModel;
|
|
26
40
|
}
|
|
@@ -1,80 +1,81 @@
|
|
|
1
|
+
import "../../ui/input.css";
|
|
1
2
|
import { NumberInput } from "../../ui/number.input";
|
|
2
3
|
import { numeric } from "../../core/numeric";
|
|
3
4
|
import { helper } from "../../core/helper";
|
|
4
5
|
import { EventHandler } from "../../interaction/eventhandler";
|
|
5
6
|
export class NumberComponent {
|
|
6
7
|
constructor(options) {
|
|
7
|
-
|
|
8
|
-
this.
|
|
9
|
-
|
|
10
|
-
this.options.value = (((_a = this.options.converter) === null || _a === void 0 ? void 0 : _a.toUI) ?
|
|
11
|
-
this.options.converter.toUI(this.options.bindTo[this.options.property]) :
|
|
12
|
-
this.options.bindTo[this.options.property]);
|
|
8
|
+
this.options = { enabled: true, format: "0.###", bindMode: "toModel", ...options };
|
|
9
|
+
if (this.hasBinding() && this.options.value == null) {
|
|
10
|
+
this.options.value = this.readModel();
|
|
13
11
|
}
|
|
12
|
+
this.modelValue = this.options.value;
|
|
14
13
|
this.options.onChange = EventHandler.Create(this.options.onChange);
|
|
15
14
|
this.id = options.id || helper.newDomGuid();
|
|
16
15
|
}
|
|
17
|
-
get onChange() {
|
|
18
|
-
return this.options.onChange;
|
|
19
|
-
}
|
|
16
|
+
get onChange() { return this.options.onChange; }
|
|
20
17
|
render() {
|
|
21
|
-
var _a;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
|
|
29
|
-
val = newVal;
|
|
30
|
-
if (newValStr !== current) {
|
|
31
|
-
if (this.currentDom != null) {
|
|
32
|
-
this.currentDom.value = newValStr;
|
|
18
|
+
var _a, _b;
|
|
19
|
+
if (this.options.bindMode !== "toModel" && this.hasBinding()) {
|
|
20
|
+
const value = this.readModel();
|
|
21
|
+
if (!Object.is(value, this.modelValue)) {
|
|
22
|
+
this.options.value = value;
|
|
23
|
+
this.modelValue = value;
|
|
24
|
+
if (this.currentDom) {
|
|
25
|
+
this.currentDom.value = numeric.format(value, this.options.format);
|
|
33
26
|
}
|
|
34
27
|
}
|
|
35
28
|
}
|
|
36
29
|
return {
|
|
37
|
-
tag: "input",
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
tag: "input", attr: {
|
|
31
|
+
id: this.id, type: "text", inputmode: (_a = this.options.inputmode) !== null && _a !== void 0 ? _a : "decimal",
|
|
32
|
+
class: (this.options.unstyled ? "" : "jsl-input ") + "jsl-number " + ((_b = this.options.class) !== null && _b !== void 0 ? _b : ""),
|
|
33
|
+
style: this.options.style, value: numeric.format(this.options.value, this.options.format),
|
|
34
|
+
placeholder: typeof this.options.placeholder === "string" ? this.options.placeholder :
|
|
35
|
+
this.options.placeholder === true ? numeric.format(0, this.options.format) : undefined,
|
|
36
|
+
disabled: this.options.enabled ? undefined : "disabled",
|
|
37
|
+
readonly: this.options.readOnly ? "readonly" : undefined,
|
|
38
|
+
"aria-label": this.options.ariaLabel
|
|
44
39
|
}
|
|
45
40
|
};
|
|
46
41
|
}
|
|
47
|
-
getValue() {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return this.currentDom.value;
|
|
52
|
-
}
|
|
53
|
-
getValueAsNumber() {
|
|
54
|
-
return numeric.parse(this.getValue());
|
|
55
|
-
}
|
|
42
|
+
getValue() { var _a, _b; return (_b = (_a = this.currentDom) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : numeric.format(this.options.value, this.options.format); }
|
|
43
|
+
getValueAsNumber() { return numeric.parse(this.getValue()); }
|
|
44
|
+
isValid() { return !this.getValue().trim() || Number.isFinite(this.getValueAsNumber()); }
|
|
45
|
+
/** Updates the input and writable binding without raising onChange. */
|
|
56
46
|
setValue(value) {
|
|
57
|
-
var _a;
|
|
58
47
|
this.options.value = value;
|
|
59
|
-
if (this.currentDom
|
|
48
|
+
if (this.currentDom) {
|
|
60
49
|
this.currentDom.value = numeric.format(value, this.options.format);
|
|
50
|
+
this.currentDom.setCustomValidity("");
|
|
51
|
+
this.currentDom.removeAttribute("aria-invalid");
|
|
61
52
|
}
|
|
62
|
-
|
|
63
|
-
this.options.bindTo[this.options.property] =
|
|
64
|
-
this.options.bindTo[this.options.property] = ((_a = this.options.converter) === null || _a === void 0 ? void 0 : _a.toData) ? this.options.converter.toData(value) : value;
|
|
65
|
-
}
|
|
53
|
+
this.writeModel(value);
|
|
66
54
|
}
|
|
55
|
+
focus() { var _a; (_a = this.currentDom) === null || _a === void 0 ? void 0 : _a.focus(); }
|
|
56
|
+
onInit(renderer) { this.renderer = renderer; }
|
|
67
57
|
onCreate(node) {
|
|
68
58
|
this.currentDom = node.dom;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
59
|
+
NumberInput(this.currentDom, { ...this.options, onChange: value => {
|
|
60
|
+
var _a;
|
|
61
|
+
this.options.value = value;
|
|
62
|
+
this.writeModel(value);
|
|
63
|
+
this.onChange.notify(value);
|
|
64
|
+
(_a = this.renderer) === null || _a === void 0 ? void 0 : _a.refresh();
|
|
65
|
+
} });
|
|
66
|
+
}
|
|
67
|
+
onRemove() { this.currentDom = null; }
|
|
68
|
+
hasBinding() { return this.options.bindTo != null && this.options.property != null; }
|
|
69
|
+
readModel() {
|
|
70
|
+
var _a;
|
|
71
|
+
const value = this.options.bindTo[this.options.property];
|
|
72
|
+
return ((_a = this.options.converter) === null || _a === void 0 ? void 0 : _a.toUI) ? this.options.converter.toUI(value) : value;
|
|
73
|
+
}
|
|
74
|
+
writeModel(value) {
|
|
75
|
+
var _a;
|
|
76
|
+
if (this.hasBinding() && this.options.bindMode !== "fromModel") {
|
|
77
|
+
this.options.bindTo[this.options.property] = ((_a = this.options.converter) === null || _a === void 0 ? void 0 : _a.toData) ? this.options.converter.toData(value) : value;
|
|
78
|
+
this.modelValue = value;
|
|
79
|
+
}
|
|
79
80
|
}
|
|
80
81
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./overlay.css";
|
|
2
|
-
import { IJSLComponent, IJSLVNode } from "jsl-render";
|
|
2
|
+
import { IJSLComponent, IJSLVNode, JSLRender } from "jsl-render";
|
|
3
3
|
export interface IOverlayComponentOptions {
|
|
4
4
|
content: IJSLVNode | string | IJSLComponent;
|
|
5
5
|
showCloseButton?: boolean;
|
|
@@ -12,16 +12,22 @@ export interface IOverlayComponentOptions {
|
|
|
12
12
|
size?: string;
|
|
13
13
|
class?: string;
|
|
14
14
|
style?: string;
|
|
15
|
+
ariaLabel?: string;
|
|
16
|
+
closeButtonLabel?: string;
|
|
15
17
|
}
|
|
16
18
|
export declare class OverlayComponent implements IJSLComponent {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
19
|
+
State: {
|
|
20
|
+
closed: boolean;
|
|
21
|
+
};
|
|
22
|
+
private dom;
|
|
23
|
+
private renderer;
|
|
24
|
+
private disposeHost?;
|
|
22
25
|
private options;
|
|
26
|
+
static show(options: IOverlayComponentOptions): OverlayComponent;
|
|
23
27
|
constructor(options: IOverlayComponentOptions);
|
|
28
|
+
onInit(renderer: JSLRender): void;
|
|
24
29
|
onCreate(node: IJSLVNode): void;
|
|
30
|
+
onRemove(): void;
|
|
31
|
+
close(): void;
|
|
25
32
|
render(): IJSLVNode;
|
|
26
|
-
private toNode;
|
|
27
33
|
}
|