@web-atoms/web-controls 2.3.109 → 2.3.110
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/dist/animations/Animations.d.ts.map +1 -1
- package/dist/animations/Animations.js +34 -8
- package/dist/animations/Animations.js.map +1 -1
- package/dist/basic/Form.d.ts +29 -73
- package/dist/basic/Form.d.ts.map +1 -1
- package/dist/basic/Form.js +85 -283
- package/dist/basic/Form.js.map +1 -1
- package/dist/basic/FormField.d.ts +1 -0
- package/dist/basic/FormField.d.ts.map +1 -1
- package/dist/basic/FormField.js +3 -14
- package/dist/basic/FormField.js.map +1 -1
- package/dist/basic/InlinePopup.d.ts +1 -0
- package/dist/basic/InlinePopup.d.ts.map +1 -1
- package/dist/basic/InlinePopup.js +2 -4
- package/dist/basic/InlinePopup.js.map +1 -1
- package/dist/basic/ListRepeater.d.ts +1 -0
- package/dist/basic/ListRepeater.d.ts.map +1 -1
- package/dist/basic/ListRepeater.js +3 -8
- package/dist/basic/ListRepeater.js.map +1 -1
- package/dist/basic/MaskedInput.d.ts +1 -0
- package/dist/basic/MaskedInput.d.ts.map +1 -1
- package/dist/basic/MaskedInput.js +3 -8
- package/dist/basic/MaskedInput.js.map +1 -1
- package/dist/basic/MaskedInputDiv.d.ts +1 -0
- package/dist/basic/MaskedInputDiv.d.ts.map +1 -1
- package/dist/basic/MaskedInputDiv.js +3 -16
- package/dist/basic/MaskedInputDiv.js.map +1 -1
- package/dist/basic/OldForm.d.ts +79 -0
- package/dist/basic/OldForm.d.ts.map +1 -0
- package/dist/basic/OldForm.js +318 -0
- package/dist/basic/OldForm.js.map +1 -0
- package/dist/basic/PasswordBox.d.ts +1 -0
- package/dist/basic/PasswordBox.d.ts.map +1 -1
- package/dist/basic/PasswordBox.js +3 -8
- package/dist/basic/PasswordBox.js.map +1 -1
- package/dist/basic/PinchZoomView.d.ts +1 -0
- package/dist/basic/PinchZoomView.d.ts.map +1 -1
- package/dist/basic/PinchZoomView.js +3 -13
- package/dist/basic/PinchZoomView.js.map +1 -1
- package/dist/basic/PopupButton.d.ts +1 -0
- package/dist/basic/PopupButton.d.ts.map +1 -1
- package/dist/basic/PopupButton.js +3 -13
- package/dist/basic/PopupButton.js.map +1 -1
- package/dist/basic/RadioButtonList.d.ts +1 -0
- package/dist/basic/RadioButtonList.d.ts.map +1 -1
- package/dist/basic/RadioButtonList.js +4 -17
- package/dist/basic/RadioButtonList.js.map +1 -1
- package/dist/basic/Swipe.d.ts +1 -0
- package/dist/basic/Swipe.d.ts.map +1 -1
- package/dist/basic/Swipe.js +3 -9
- package/dist/basic/Swipe.js.map +1 -1
- package/dist/basic/Switch.d.ts +4 -0
- package/dist/basic/Switch.d.ts.map +1 -1
- package/dist/basic/Switch.js +4 -23
- package/dist/basic/Switch.js.map +1 -1
- package/dist/basic/TableRepeater.d.ts.map +1 -1
- package/dist/basic/TableRepeater.js +2 -7
- package/dist/basic/TableRepeater.js.map +1 -1
- package/dist/basic/TimeEditor.d.ts +1 -0
- package/dist/basic/TimeEditor.d.ts.map +1 -1
- package/dist/basic/TimeEditor.js +3 -13
- package/dist/basic/TimeEditor.js.map +1 -1
- package/dist/basic/TitleEditor.d.ts +1 -0
- package/dist/basic/TitleEditor.d.ts.map +1 -1
- package/dist/basic/TitleEditor.js +3 -8
- package/dist/basic/TitleEditor.js.map +1 -1
- package/dist/basic/ToggleButtonBar.d.ts +1 -0
- package/dist/basic/ToggleButtonBar.d.ts.map +1 -1
- package/dist/basic/ToggleButtonBar.js +3 -10
- package/dist/basic/ToggleButtonBar.js.map +1 -1
- package/dist/basic/Tooltip.d.ts +1 -0
- package/dist/basic/Tooltip.d.ts.map +1 -1
- package/dist/basic/Tooltip.js +3 -8
- package/dist/basic/Tooltip.js.map +1 -1
- package/dist/basic/styles/form-field-style.d.ts +2 -0
- package/dist/basic/styles/form-field-style.d.ts.map +1 -0
- package/dist/basic/styles/form-field-style.js +146 -0
- package/dist/basic/styles/form-field-style.js.map +1 -0
- package/dist/basic/styles/inline-popup-style.d.ts +2 -0
- package/dist/basic/styles/inline-popup-style.d.ts.map +1 -0
- package/dist/basic/styles/inline-popup-style.js +28 -0
- package/dist/basic/styles/inline-popup-style.js.map +1 -0
- package/dist/basic/styles/list-repeater-style.d.ts +2 -0
- package/dist/basic/styles/list-repeater-style.d.ts.map +1 -0
- package/dist/basic/styles/list-repeater-style.js +36 -0
- package/dist/basic/styles/list-repeater-style.js.map +1 -0
- package/dist/basic/styles/masked-input-div.d.ts +2 -0
- package/dist/basic/styles/masked-input-div.d.ts.map +1 -0
- package/dist/basic/styles/masked-input-div.js +52 -0
- package/dist/basic/styles/masked-input-div.js.map +1 -0
- package/dist/basic/styles/masked-input-style.d.ts +2 -0
- package/dist/basic/styles/masked-input-style.d.ts.map +1 -0
- package/dist/basic/styles/masked-input-style.js +19 -0
- package/dist/basic/styles/masked-input-style.js.map +1 -0
- package/dist/basic/styles/password-box-style.d.ts +2 -0
- package/dist/basic/styles/password-box-style.d.ts.map +1 -0
- package/dist/basic/styles/password-box-style.js +35 -0
- package/dist/basic/styles/password-box-style.js.map +1 -0
- package/dist/basic/styles/pinch-zoom-view-style.d.ts +2 -0
- package/dist/basic/styles/pinch-zoom-view-style.d.ts.map +1 -0
- package/dist/basic/styles/pinch-zoom-view-style.js +61 -0
- package/dist/basic/styles/pinch-zoom-view-style.js.map +1 -0
- package/dist/basic/styles/popup-button-style.d.ts +2 -0
- package/dist/basic/styles/popup-button-style.d.ts.map +1 -0
- package/dist/basic/styles/popup-button-style.js +40 -0
- package/dist/basic/styles/popup-button-style.js.map +1 -0
- package/dist/basic/styles/radio-button-list-style.d.ts +2 -0
- package/dist/basic/styles/radio-button-list-style.d.ts.map +1 -0
- package/dist/basic/styles/radio-button-list-style.js +44 -0
- package/dist/basic/styles/radio-button-list-style.js.map +1 -0
- package/dist/basic/styles/swipe-style.d.ts +2 -0
- package/dist/basic/styles/swipe-style.d.ts.map +1 -0
- package/dist/basic/styles/swipe-style.js +32 -0
- package/dist/basic/styles/swipe-style.js.map +1 -0
- package/dist/basic/styles/switch-style.d.ts +2 -0
- package/dist/basic/styles/switch-style.d.ts.map +1 -0
- package/dist/basic/styles/switch-style.js +127 -0
- package/dist/basic/styles/switch-style.js.map +1 -0
- package/dist/basic/styles/time-editor-style.d.ts +2 -0
- package/dist/basic/styles/time-editor-style.d.ts.map +1 -0
- package/dist/basic/styles/time-editor-style.js +64 -0
- package/dist/basic/styles/time-editor-style.js.map +1 -0
- package/dist/basic/styles/title-editor-style.d.ts +2 -0
- package/dist/basic/styles/title-editor-style.d.ts.map +1 -0
- package/dist/basic/styles/title-editor-style.js +45 -0
- package/dist/basic/styles/title-editor-style.js.map +1 -0
- package/dist/basic/styles/toggle-button-bar-style.d.ts +2 -0
- package/dist/basic/styles/toggle-button-bar-style.d.ts.map +1 -0
- package/dist/basic/styles/toggle-button-bar-style.js +48 -0
- package/dist/basic/styles/toggle-button-bar-style.js.map +1 -0
- package/dist/basic/styles/toggle-view-style.d.ts +2 -0
- package/dist/basic/styles/toggle-view-style.d.ts.map +1 -0
- package/dist/basic/styles/toggle-view-style.js +91 -0
- package/dist/basic/styles/toggle-view-style.js.map +1 -0
- package/dist/basic/styles/tooltip-style.d.ts +2 -0
- package/dist/basic/styles/tooltip-style.d.ts.map +1 -0
- package/dist/basic/styles/tooltip-style.js +21 -0
- package/dist/basic/styles/tooltip-style.js.map +1 -0
- package/dist/html-editor/InlineHtmlEditor.d.ts.map +1 -1
- package/dist/html-editor/InlineHtmlEditor.js +29 -7
- package/dist/html-editor/InlineHtmlEditor.js.map +1 -1
- package/dist/mobile-app/BottomPopup.d.ts.map +1 -1
- package/dist/mobile-app/BottomPopup.js +76 -14
- package/dist/mobile-app/BottomPopup.js.map +1 -1
- package/dist/mobile-app/MobileApp.d.ts.map +1 -1
- package/dist/mobile-app/MobileApp.js +226 -26
- package/dist/mobile-app/MobileApp.js.map +1 -1
- package/dist/player/AtomVideoPlayer.d.ts.map +1 -1
- package/dist/player/AtomVideoPlayer.js +160 -13
- package/dist/player/AtomVideoPlayer.js.map +1 -1
- package/dist/toggle-view/AtomToggleView.d.ts +1 -0
- package/dist/toggle-view/AtomToggleView.d.ts.map +1 -1
- package/dist/toggle-view/AtomToggleView.js +3 -16
- package/dist/toggle-view/AtomToggleView.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/animations/Animations.ts +32 -28
- package/src/basic/Form.tsx +89 -383
- package/src/basic/FormField.tsx +1 -117
- package/src/basic/InlinePopup.tsx +1 -16
- package/src/basic/ListRepeater.tsx +1 -26
- package/src/basic/MaskedInput.tsx +2 -17
- package/src/basic/MaskedInputDiv.tsx +2 -41
- package/src/basic/OldForm.tsx +424 -0
- package/src/basic/PasswordBox.tsx +1 -22
- package/src/basic/PinchZoomView.tsx +2 -41
- package/src/basic/PopupButton.tsx +1 -19
- package/src/basic/RadioButtonList.tsx +1 -17
- package/src/basic/Swipe.tsx +1 -21
- package/src/basic/Switch.tsx +2 -83
- package/src/basic/TableRepeater.tsx +0 -3
- package/src/basic/TimeEditor.tsx +2 -40
- package/src/basic/TitleEditor.tsx +1 -28
- package/src/basic/ToggleButtonBar.tsx +1 -30
- package/src/basic/Tooltip.tsx +2 -5
- package/src/basic/styles/form-field-style.ts +136 -0
- package/src/basic/styles/inline-popup-style.ts +19 -0
- package/src/basic/styles/list-repeater-style.ts +25 -0
- package/src/basic/styles/masked-input-div.ts +41 -0
- package/src/basic/styles/masked-input-style.ts +8 -0
- package/src/basic/styles/password-box-style.ts +24 -0
- package/src/basic/styles/pinch-zoom-view-style.ts +50 -0
- package/src/basic/styles/popup-button-style.ts +30 -0
- package/src/basic/styles/radio-button-list-style.ts +34 -0
- package/src/basic/styles/swipe-style.ts +22 -0
- package/src/basic/styles/switch-style.ts +116 -0
- package/src/basic/styles/time-editor-style.ts +53 -0
- package/src/basic/styles/title-editor-style.ts +34 -0
- package/src/basic/styles/toggle-button-bar-style.ts +37 -0
- package/src/basic/styles/toggle-view-style.ts +80 -0
- package/src/basic/styles/tooltip-style.ts +10 -0
- package/src/html-editor/InlineHtmlEditor.tsx +26 -16
- package/src/mobile-app/BottomPopup.tsx +73 -68
- package/src/mobile-app/MobileApp.tsx +227 -174
- package/src/player/AtomVideoPlayer.tsx +157 -141
- package/src/toggle-view/AtomToggleView.tsx +3 -53
- package/dist/basic/Form2.d.ts +0 -27
- package/dist/basic/Form2.d.ts.map +0 -1
- package/dist/basic/Form2.js +0 -120
- package/dist/basic/Form2.js.map +0 -1
- package/dist/basic/FormDialog.d.ts +0 -4
- package/dist/basic/FormDialog.d.ts.map +0 -1
- package/dist/basic/FormDialog.js +0 -32
- package/dist/basic/FormDialog.js.map +0 -1
- package/dist/basic/Input.d.ts +0 -5
- package/dist/basic/Input.d.ts.map +0 -1
- package/dist/basic/Input.js +0 -30
- package/dist/basic/Input.js.map +0 -1
- package/dist/basic/Mix.d.ts +0 -10
- package/dist/basic/Mix.d.ts.map +0 -1
- package/dist/basic/Mix.js +0 -31
- package/dist/basic/Mix.js.map +0 -1
- package/dist/basic/Panel.d.ts +0 -6
- package/dist/basic/Panel.d.ts.map +0 -1
- package/dist/basic/Panel.js +0 -37
- package/dist/basic/Panel.js.map +0 -1
- package/dist/basic/Row.d.ts +0 -15
- package/dist/basic/Row.d.ts.map +0 -1
- package/dist/basic/Row.js +0 -43
- package/dist/basic/Row.js.map +0 -1
- package/dist/switch/AtomSwitch.d.ts +0 -7
- package/dist/switch/AtomSwitch.d.ts.map +0 -1
- package/dist/switch/AtomSwitch.js +0 -42
- package/dist/switch/AtomSwitch.js.map +0 -1
- package/dist/switch/AtomSwitchStyle.d.ts +0 -8
- package/dist/switch/AtomSwitchStyle.d.ts.map +0 -1
- package/dist/switch/AtomSwitchStyle.js +0 -80
- package/dist/switch/AtomSwitchStyle.js.map +0 -1
- package/src/basic/Form2.tsx +0 -121
- package/src/basic/FormDialog.tsx +0 -28
- package/src/basic/Input.tsx +0 -30
- package/src/basic/Mix.tsx +0 -25
- package/src/basic/Panel.tsx +0 -43
- package/src/basic/Row.tsx +0 -49
- package/src/switch/AtomSwitch.tsx +0 -24
- package/src/switch/AtomSwitchStyle.ts +0 -71
package/src/basic/Form.tsx
CHANGED
|
@@ -1,424 +1,130 @@
|
|
|
1
1
|
import Bind from "@web-atoms/core/dist/core/Bind";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import StyleRule from "@web-atoms/core/dist/style/StyleRule";
|
|
5
|
-
import { ChildEnumerator } from "@web-atoms/core/dist/web/core/AtomUI";
|
|
6
|
-
import CSS from "@web-atoms/core/dist/web/styles/CSS";
|
|
7
|
-
import FormField from "./FormField";
|
|
8
|
-
import IElement from "./IElement";
|
|
9
|
-
import ToggleButtonBar from "./ToggleButtonBar";
|
|
10
|
-
export const FormButtonBar = ToggleButtonBar;
|
|
2
|
+
import XNode, { elementFactorySymbol } from "@web-atoms/core/dist/core/XNode";
|
|
3
|
+
import styled from "@web-atoms/core/dist/style/styled";
|
|
11
4
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
.child(StyleRule("button")
|
|
17
|
-
.alignSelf("flex-start")
|
|
18
|
-
)
|
|
19
|
-
.and(StyleRule("[data-scrollable=true]")
|
|
20
|
-
.justifyContent("flex-start")
|
|
21
|
-
.overflow("auto")
|
|
22
|
-
)
|
|
23
|
-
, "*[data-wa-form=wa-form]");
|
|
5
|
+
styled.css `
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
gap: var(--spacing, 5px);
|
|
24
9
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
[key: string]: any;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface ISubmitAction extends IElement {
|
|
32
|
-
action: "submit";
|
|
33
|
-
eventClick?: any;
|
|
34
|
-
"event-click"?: any;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface ICancelAction extends IElement {
|
|
38
|
-
action: "cancel";
|
|
39
|
-
eventClick?: any;
|
|
40
|
-
"event-click"?: any;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export type IFormAction = ISubmitAction | ICancelAction;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* This is just a decorator, you must have a child button for this to work
|
|
47
|
-
* @param action submit | cancel
|
|
48
|
-
* @param node child node where action will be applied
|
|
49
|
-
* @returns XNode
|
|
50
|
-
*/
|
|
51
|
-
export function FormAction(
|
|
52
|
-
{
|
|
53
|
-
action = "submit",
|
|
54
|
-
eventClick,
|
|
55
|
-
"event-click": eventClick2,
|
|
56
|
-
... a
|
|
57
|
-
}: IFormAction,
|
|
58
|
-
node: XNode) {
|
|
59
|
-
const attributes = node.attributes ??= {};
|
|
60
|
-
attributes["data-wa-form-action"] = action;
|
|
61
|
-
const e = attributes["event-click"] || attributes.eventClick;
|
|
62
|
-
if (e) {
|
|
63
|
-
attributes["event-submit"] = e;
|
|
64
|
-
delete attributes["event-click"];
|
|
65
|
-
delete attributes.eventClick;
|
|
66
|
-
}
|
|
67
|
-
eventClick ??= eventClick2;
|
|
68
|
-
if (action === "submit" && eventClick) {
|
|
69
|
-
attributes.eventSubmit = eventClick;
|
|
70
|
-
}
|
|
71
|
-
node.attributes = { ... a, ... attributes};
|
|
72
|
-
return node;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* @deprecated Use Form with eventSubmit and button with data-event="submit"
|
|
77
|
-
*/
|
|
78
|
-
export function SubmitAction(a: IElement, node: XNode) {
|
|
79
|
-
(a as any).action = "submit";
|
|
80
|
-
return FormAction(a as any, node);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @deprecated Use Form with eventSubmit and button with data-event="submit"
|
|
85
|
-
*/
|
|
86
|
-
export function CancelAction(a: IElement, node: XNode) {
|
|
87
|
-
(a as any).action = "cancel";
|
|
88
|
-
return FormAction(a as any, node);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @deprecated Use Form with eventSubmit and button with data-event="submit"
|
|
93
|
-
*/
|
|
94
|
-
export function SubmitButton(
|
|
95
|
-
{ eventClick,
|
|
96
|
-
... others}: ISubmitButton,
|
|
97
|
-
... nodes: XNode[]) {
|
|
98
|
-
return <button
|
|
99
|
-
data-wa-form-action="submit"
|
|
100
|
-
eventSubmit={eventClick} { ... others }>{ ... nodes}</button>;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function findSubmitAction(e: Event) {
|
|
104
|
-
let button = e.target as HTMLElement;
|
|
105
|
-
if (e.type === "submit") {
|
|
106
|
-
e.preventDefault();
|
|
107
|
-
button = (e as SubmitEvent).submitter;
|
|
108
|
-
}
|
|
109
|
-
while (button) {
|
|
110
|
-
const action = button.dataset.waFormAction ?? button.dataset.event;
|
|
111
|
-
if (/submit|cancel/i.test(action)) {
|
|
112
|
-
return { button, action };
|
|
10
|
+
&[data-valid=true] {
|
|
11
|
+
& .field-error:not(:empty) {
|
|
12
|
+
display: none;
|
|
113
13
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return { button };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const submitFormHandler = (form: HTMLElement) => {
|
|
120
|
-
if (!form.dataset.waShowErrors) {
|
|
121
|
-
form.dataset.waShowErrors = "yes";
|
|
122
|
-
}
|
|
123
|
-
setTimeout(() => {
|
|
124
|
-
const all = Array.from(form.getElementsByClassName("field-error"));
|
|
125
|
-
for (const iterator of all) {
|
|
126
|
-
if (iterator.textContent) {
|
|
127
|
-
alert(form.dataset?.errorMessage ?? "Please fix all validations");
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
14
|
+
& > .error-message {
|
|
15
|
+
display: none;
|
|
130
16
|
}
|
|
131
|
-
form.dispatchEvent(new CustomEvent("submitForm"));
|
|
132
|
-
}, 100);
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const checkValidity = (handler) => (e: MouseEvent) => {
|
|
136
|
-
|
|
137
|
-
const form = e.currentTarget as HTMLFormElement;
|
|
138
|
-
|
|
139
|
-
const { button, action } = findSubmitAction(e);
|
|
140
|
-
if (!button) {
|
|
141
|
-
return;
|
|
142
17
|
}
|
|
143
18
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
19
|
+
& > .error-message {
|
|
20
|
+
padding: var(--spacing-small, 2px);
|
|
21
|
+
padding-left: var(--spacing-large, 10px);
|
|
22
|
+
padding-right: var(--spacing-large, 10px);
|
|
23
|
+
background-color: red;
|
|
24
|
+
border-radius: 9999px;
|
|
25
|
+
color: white;
|
|
26
|
+
position: sticky;
|
|
147
27
|
}
|
|
28
|
+
`.installGlobal("[data-form=form]");
|
|
148
29
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (action === "cancel") {
|
|
154
|
-
form.dataset.waShowErrors = "";
|
|
30
|
+
const checkClick = (e: MouseEvent) => {
|
|
31
|
+
const form = e.currentTarget as HTMLDivElement;
|
|
32
|
+
const target = e.target as HTMLButtonElement;
|
|
33
|
+
if (!/submit/i.test(target.type ?? target.getAttribute("data-type") )) {
|
|
155
34
|
return;
|
|
156
35
|
}
|
|
157
|
-
|
|
158
|
-
form.dataset.waShowErrors = "yes";
|
|
159
|
-
}
|
|
160
|
-
|
|
36
|
+
form.setAttribute("data-show-validation", "true");
|
|
161
37
|
setTimeout(() => {
|
|
162
38
|
const all = Array.from(form.getElementsByClassName("field-error"));
|
|
163
39
|
for (const iterator of all) {
|
|
164
40
|
if (iterator.textContent) {
|
|
165
|
-
|
|
41
|
+
form.setAttribute("data-valid", "false");
|
|
166
42
|
return;
|
|
167
43
|
}
|
|
168
44
|
}
|
|
169
|
-
|
|
45
|
+
form.setAttribute("data-valid", "true");
|
|
46
|
+
target.dispatchEvent(new CustomEvent(form.getAttribute("data-submit-event"), { bubbles: true, cancelable: true }));
|
|
170
47
|
}, 100);
|
|
171
48
|
};
|
|
172
49
|
|
|
173
|
-
|
|
174
|
-
if (!/enter|submit|return/i.test(e.key)) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
const element = e.target as HTMLElement;
|
|
178
|
-
if (!element.tagName) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
if (handler) {
|
|
182
|
-
if (/^INPUT$/.test(element.tagName)) {
|
|
183
|
-
submitFormHandler(e.currentTarget as HTMLElement);
|
|
184
|
-
}
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
if (element.dataset.waFormAction === "submit") {
|
|
188
|
-
element.dispatchEvent(new MouseEvent("click"));
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
if (/input/i.test(element.tagName)) {
|
|
192
|
-
e.preventDefault();
|
|
193
|
-
element.dispatchEvent(new KeyboardEvent("keypress", {
|
|
194
|
-
key: "tab"
|
|
195
|
-
}));
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
document.body.addEventListener("click", (e: MouseEvent) => {
|
|
200
|
-
let start = e.target as HTMLElement;
|
|
201
|
-
let id;
|
|
202
|
-
while (start) {
|
|
203
|
-
id = start.dataset.submitFormId;
|
|
204
|
-
if (id) {
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
start = start.parentElement;
|
|
208
|
-
}
|
|
209
|
-
if (!start) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
const form = document.body.querySelector(`[data-form-id="${id}"]`);
|
|
213
|
-
submitFormHandler(form as HTMLElement);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
export interface IForm {
|
|
217
|
-
id?: number;
|
|
218
|
-
class?: any;
|
|
219
|
-
scrollable?: boolean ;
|
|
50
|
+
export interface IForm2 {
|
|
220
51
|
/**
|
|
221
|
-
*
|
|
222
|
-
* non textarea element, form will be submitted automatically
|
|
52
|
+
* The event that will be dispatched, default is `submitForm`
|
|
223
53
|
*/
|
|
224
|
-
|
|
54
|
+
"data-submit-event"?: string;
|
|
225
55
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
56
|
+
* Validation will be displayed if set to true, default is false.
|
|
57
|
+
* It will be set to true if button with type=submit or data-type=submit will be clicked.
|
|
228
58
|
*/
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
let formId = 0;
|
|
236
|
-
|
|
237
|
-
const formGroupSymbol = Symbol("formGroup");
|
|
59
|
+
"data-show-validation"?: "true" | "false"
|
|
60
|
+
/**
|
|
61
|
+
* Default error message to be displayed if any field contains error.
|
|
62
|
+
*/
|
|
63
|
+
"data-error-message"?: string;
|
|
238
64
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Please change your form style to catch event-submit-form
|
|
67
|
+
*/
|
|
68
|
+
eventSubmit?: never;
|
|
69
|
+
/**
|
|
70
|
+
* Please change your form style to catch event-submit-form
|
|
71
|
+
*/
|
|
72
|
+
submitCommand?: never;
|
|
243
73
|
}
|
|
244
74
|
|
|
245
|
-
export function
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
75
|
+
export default function Form({
|
|
76
|
+
"data-submit-event": submitEvent = "submitForm",
|
|
77
|
+
"data-show-validation": showValidation = "false",
|
|
78
|
+
"data-error-message": errorMessage = "Please fix all validations",
|
|
79
|
+
... a
|
|
80
|
+
}: IForm2, ... nodes: XNode[]) {
|
|
250
81
|
return <div
|
|
251
|
-
{ ...
|
|
82
|
+
{ ... a}
|
|
83
|
+
data-submit-event={submitEvent}
|
|
84
|
+
data-form="form"
|
|
85
|
+
data-valid="true"
|
|
86
|
+
data-show-validation={showValidation}
|
|
87
|
+
data-error-message={errorMessage}
|
|
88
|
+
event-click={checkClick}>
|
|
89
|
+
<div class="error-message" text={errorMessage}/>
|
|
252
90
|
{ ... nodes}
|
|
253
91
|
</div>;
|
|
254
92
|
}
|
|
255
93
|
|
|
256
|
-
|
|
257
|
-
{
|
|
258
|
-
id = formId++,
|
|
259
|
-
focusNextOnEnter = true,
|
|
260
|
-
scrollable,
|
|
261
|
-
eventSubmit,
|
|
262
|
-
submitCommand,
|
|
263
|
-
... a
|
|
264
|
-
}: IForm,
|
|
265
|
-
... nodes: XNode[]) {
|
|
266
|
-
if (focusNextOnEnter) {
|
|
267
|
-
a.eventKeypress = moveNext(eventSubmit);
|
|
268
|
-
}
|
|
269
|
-
a["data-form-id"] = id;
|
|
270
|
-
a["data-scrollable"] = !!scrollable;
|
|
271
|
-
if (!eventSubmit) {
|
|
272
|
-
a["data-wa-show-errors"] = "yes";
|
|
273
|
-
}
|
|
274
|
-
if (submitCommand) {
|
|
275
|
-
a["event-" + submitCommand.name] = checkValidity(eventSubmit);
|
|
276
|
-
}
|
|
277
|
-
const fields = [];
|
|
278
|
-
for (const iterator of nodes) {
|
|
279
|
-
if (!iterator) {
|
|
280
|
-
continue;
|
|
281
|
-
}
|
|
282
|
-
const ca = iterator.attributes as any;
|
|
283
|
-
if (ca?.[formGroupSymbol]) {
|
|
284
|
-
for (const child of iterator.children) {
|
|
285
|
-
const cha = child.attributes ??= {};
|
|
286
|
-
cha["data-group"] = ca.group;
|
|
287
|
-
fields.push(child);
|
|
288
|
-
}
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
fields.push(iterator);
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return <div
|
|
295
|
-
data-wa-form="wa-form"
|
|
296
|
-
{ ... a}
|
|
297
|
-
eventSubmitForm={eventSubmit}
|
|
298
|
-
eventClick={checkValidity(eventSubmit)}>
|
|
299
|
-
{ ... fields}
|
|
300
|
-
</div>;
|
|
301
|
-
}
|
|
94
|
+
type Func = (... p: any[]) => any;
|
|
302
95
|
|
|
303
|
-
export interface
|
|
304
|
-
|
|
305
|
-
|
|
96
|
+
export interface IValidator {
|
|
97
|
+
value: Func;
|
|
98
|
+
message?: (value: string, label: string) => string;
|
|
99
|
+
isValid?: (value: string, element: HTMLElement) => boolean;
|
|
306
100
|
}
|
|
307
101
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
.gridRowStart("2")
|
|
320
|
-
.overflow("auto")
|
|
321
|
-
.child(StyleRule("div")
|
|
322
|
-
.verticalFlexLayout({ alignItems: "stretch", gap: 10 })
|
|
323
|
-
)
|
|
324
|
-
)
|
|
325
|
-
.child(StyleRule("[data-element=footer]")
|
|
326
|
-
.gridRowStart("3")
|
|
327
|
-
)
|
|
328
|
-
, "*[data-form-layout=form-layout]");
|
|
329
|
-
|
|
330
|
-
const elementType = Symbol.for("elementType");
|
|
331
|
-
|
|
332
|
-
export function FormLayout(
|
|
333
|
-
{
|
|
334
|
-
id = formId++,
|
|
335
|
-
focusNextOnEnter = true,
|
|
336
|
-
scrollable,
|
|
337
|
-
eventSubmit,
|
|
338
|
-
header,
|
|
339
|
-
footer,
|
|
340
|
-
... a
|
|
341
|
-
}: IFormLayout,
|
|
342
|
-
... nodes: XNode[]) {
|
|
343
|
-
if (focusNextOnEnter) {
|
|
344
|
-
a.eventKeypress = moveNext(eventSubmit);
|
|
345
|
-
}
|
|
346
|
-
a["data-form-id"] = id;
|
|
347
|
-
a["data-scrollable"] = !!scrollable;
|
|
348
|
-
if (!eventSubmit) {
|
|
349
|
-
a["data-wa-show-errors"] = "yes";
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const fields = [];
|
|
353
|
-
for (const iterator of nodes) {
|
|
354
|
-
if (!iterator) {
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const et = iterator[elementType];
|
|
359
|
-
if (et !== void 0) {
|
|
360
|
-
if (et === "header") {
|
|
361
|
-
header = iterator;
|
|
362
|
-
delete iterator[elementType];
|
|
363
|
-
continue;
|
|
364
|
-
}
|
|
365
|
-
if (et === "footer") {
|
|
366
|
-
footer = iterator;
|
|
367
|
-
delete iterator[elementType];
|
|
368
|
-
continue;
|
|
102
|
+
export const BindError = ({
|
|
103
|
+
value,
|
|
104
|
+
message = (v, l) => `${l} is invalid`,
|
|
105
|
+
isValid = (v, e) => !!v,
|
|
106
|
+
}: IValidator) => {
|
|
107
|
+
function f2 (sender, element: HTMLElement) {
|
|
108
|
+
const isRequired = element.parentElement.querySelector(`[data-required]`);
|
|
109
|
+
const msg = value.call(this, sender);
|
|
110
|
+
if (!msg) {
|
|
111
|
+
if (!isRequired) {
|
|
112
|
+
return "";
|
|
369
113
|
}
|
|
370
114
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (ca?.[formGroupSymbol]) {
|
|
374
|
-
for (const child of iterator.children) {
|
|
375
|
-
const cha = child.attributes ??= {};
|
|
376
|
-
cha["data-group"] = ca.group;
|
|
377
|
-
fields.push(child);
|
|
378
|
-
}
|
|
379
|
-
continue;
|
|
115
|
+
if (isValid(msg, element)) {
|
|
116
|
+
return "";
|
|
380
117
|
}
|
|
381
|
-
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const ha = header.attributes ??= {};
|
|
386
|
-
ha["data-element"] = "header";
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (footer) {
|
|
390
|
-
const ha = footer.attributes ??= {};
|
|
391
|
-
ha["data-element"] = "footer";
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
return <div
|
|
395
|
-
data-wa-form="wa-form"
|
|
396
|
-
data-form-layout="form-layout"
|
|
397
|
-
{ ... a}
|
|
398
|
-
eventSubmitForm={eventSubmit}
|
|
399
|
-
eventClick={checkValidity(eventSubmit)}>
|
|
400
|
-
{ header }
|
|
401
|
-
<div data-element="content">
|
|
402
|
-
<div>
|
|
403
|
-
{ ... fields}
|
|
404
|
-
</div>
|
|
405
|
-
</div>
|
|
406
|
-
{ footer }
|
|
407
|
-
</div>;
|
|
118
|
+
return message(msg, element.parentElement.querySelector(`[data-element=label]`)?.textContent || "This field ");
|
|
119
|
+
};
|
|
120
|
+
f2.toString = () => value.toString();
|
|
121
|
+
return Bind.oneWay(f2);
|
|
408
122
|
}
|
|
409
123
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
return child;
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
Form.newId = () => formId++;
|
|
421
|
-
|
|
422
|
-
Form.submitId = (id: number) => ({
|
|
423
|
-
"data-submit-form-id": id.toString()
|
|
424
|
-
});
|
|
124
|
+
export const BindEmailError = ({
|
|
125
|
+
value,
|
|
126
|
+
message = (v, l) => `${l} is not a valid email address`,
|
|
127
|
+
isValid = (v, e) => /[^\@]+\@[^\@]+\.[^\@]+/i.test(v),
|
|
128
|
+
}: IValidator) => {
|
|
129
|
+
return BindError({ value, message, isValid });
|
|
130
|
+
}
|
package/src/basic/FormField.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import StyleRule from "@web-atoms/core/dist/style/StyleRule";
|
|
|
9
9
|
import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
|
|
10
10
|
import PopupService, { PopupWindow } from "@web-atoms/core/dist/web/services/PopupService";
|
|
11
11
|
import CSS from "@web-atoms/core/dist/web/styles/CSS";
|
|
12
|
+
import "./styles/form-field-style";
|
|
12
13
|
|
|
13
14
|
export interface IFormField {
|
|
14
15
|
label: string | XNode;
|
|
@@ -31,123 +32,6 @@ export interface IFormField {
|
|
|
31
32
|
[key: string]: any;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
const css = CSS(StyleRule()
|
|
35
|
-
.display("grid")
|
|
36
|
-
.alignItems("center")
|
|
37
|
-
.gridTemplateColumns("auto 1fr auto auto")
|
|
38
|
-
.gridTemplateRows("auto auto auto")
|
|
39
|
-
.child(StyleRule("[data-element=label]")
|
|
40
|
-
.gridRow("1")
|
|
41
|
-
.gridColumn("1")
|
|
42
|
-
)
|
|
43
|
-
.child(StyleRule("[data-element=content]")
|
|
44
|
-
.gridRowStart("2")
|
|
45
|
-
.gridColumnStart("1")
|
|
46
|
-
.gridColumnEnd("span 2")
|
|
47
|
-
.marginTop(5)
|
|
48
|
-
.marginBottom(5)
|
|
49
|
-
)
|
|
50
|
-
.and(StyleRule("[data-border=true]")
|
|
51
|
-
.nested(StyleRule("input")
|
|
52
|
-
.border("none")
|
|
53
|
-
.outline("none")
|
|
54
|
-
)
|
|
55
|
-
.nested(StyleRule("textarea")
|
|
56
|
-
.border("none")
|
|
57
|
-
.outline("none")
|
|
58
|
-
)
|
|
59
|
-
.nested(StyleRule("select")
|
|
60
|
-
.border("none")
|
|
61
|
-
)
|
|
62
|
-
)
|
|
63
|
-
.child(StyleRule("i[data-border=border]")
|
|
64
|
-
.gridColumnStart("1")
|
|
65
|
-
.gridColumnEnd("span 3")
|
|
66
|
-
.gridRowStart("3")
|
|
67
|
-
.alignSelf("flex-end")
|
|
68
|
-
.borderBottomStyle("solid")
|
|
69
|
-
.borderBottomWidth("1px")
|
|
70
|
-
.borderBottomColor(Colors.lightGray)
|
|
71
|
-
)
|
|
72
|
-
.and(StyleRule("[data-focused=true]")
|
|
73
|
-
.child(StyleRule("i[data-border=border]")
|
|
74
|
-
.borderBottomColor(Colors.black)
|
|
75
|
-
)
|
|
76
|
-
)
|
|
77
|
-
.child(StyleRule("i[data-help=help]")
|
|
78
|
-
.gridRowStart("2")
|
|
79
|
-
.gridColumnStart("3")
|
|
80
|
-
.padding(5)
|
|
81
|
-
.fontSize("x-large")
|
|
82
|
-
.cursor("pointer")
|
|
83
|
-
.marginLeft("auto")
|
|
84
|
-
.color(Colors.lightGreen)
|
|
85
|
-
)
|
|
86
|
-
.child(StyleRule(".field-error")
|
|
87
|
-
.gridRowStart("4")
|
|
88
|
-
.gridColumnStart("1")
|
|
89
|
-
.gridColumnEnd("span 3")
|
|
90
|
-
.padding(5)
|
|
91
|
-
.margin(5)
|
|
92
|
-
.borderRadius(9999)
|
|
93
|
-
.backgroundColor(Colors.red)
|
|
94
|
-
.color(Colors.white)
|
|
95
|
-
.fontSize("smaller")
|
|
96
|
-
.and(StyleRule(":empty")
|
|
97
|
-
.display("none")
|
|
98
|
-
)
|
|
99
|
-
)
|
|
100
|
-
.child(StyleRule("span[data-required=required]")
|
|
101
|
-
.gridColumnStart("2")
|
|
102
|
-
.gridRow("1")
|
|
103
|
-
.visibility("hidden")
|
|
104
|
-
.color(Colors.red)
|
|
105
|
-
.and(StyleRule(".true")
|
|
106
|
-
.visibility("visible")
|
|
107
|
-
)
|
|
108
|
-
)
|
|
109
|
-
.and(StyleRule("[data-layout=horizontal]")
|
|
110
|
-
.gridTemplateColumns("auto auto 1fr auto")
|
|
111
|
-
.gridTemplateRows("auto auto")
|
|
112
|
-
.child(StyleRule("label.label")
|
|
113
|
-
.gridRowStart("2")
|
|
114
|
-
.marginRight(5)
|
|
115
|
-
.marginBottom(5)
|
|
116
|
-
)
|
|
117
|
-
.child(StyleRule("[data-content=content]")
|
|
118
|
-
.gridRowStart("2")
|
|
119
|
-
.gridColumnStart("3")
|
|
120
|
-
.marginTop(0)
|
|
121
|
-
.marginBottom(5)
|
|
122
|
-
)
|
|
123
|
-
.child(StyleRule("i[data-help=help]")
|
|
124
|
-
.gridRowStart("2")
|
|
125
|
-
.gridColumnStart("4")
|
|
126
|
-
)
|
|
127
|
-
.child(StyleRule(".field-error")
|
|
128
|
-
.gridRowStart("4")
|
|
129
|
-
.gridColumnStart("1")
|
|
130
|
-
.gridColumnEnd("span 3")
|
|
131
|
-
)
|
|
132
|
-
.child(StyleRule("span[data-required=required]")
|
|
133
|
-
.gridRowStart("2")
|
|
134
|
-
.gridColumnStart("2")
|
|
135
|
-
.marginRight(5)
|
|
136
|
-
.display("none")
|
|
137
|
-
.color(Colors.red)
|
|
138
|
-
.and(StyleRule(".true")
|
|
139
|
-
.display("inline")
|
|
140
|
-
)
|
|
141
|
-
)
|
|
142
|
-
)
|
|
143
|
-
, "div[data-wa-form-field=wa-form-field]");
|
|
144
|
-
|
|
145
|
-
CSS(StyleRule()
|
|
146
|
-
.overflow("auto")
|
|
147
|
-
.padding(10)
|
|
148
|
-
.verticalFlexLayout({ alignItems: "center", justifyContent: "flex-start"})
|
|
149
|
-
, "div[data-form-field-help=help-window]");
|
|
150
|
-
|
|
151
35
|
// let id = 1;
|
|
152
36
|
// const generateId = (name: string) => {
|
|
153
37
|
// return `${name.replace(/[\W_]+/g, "-")}-${id++}`;
|
|
@@ -10,22 +10,7 @@ import { IPopupOptions } from "@web-atoms/core/dist/web/services/PopupService";
|
|
|
10
10
|
import CSS from "@web-atoms/core/dist/web/styles/CSS";
|
|
11
11
|
import IElement from "./IElement";
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
.position("absolute")
|
|
15
|
-
.borderRadius(5)
|
|
16
|
-
.padding(5)
|
|
17
|
-
.border("solid 1px lightgray")
|
|
18
|
-
.defaultBoxShadow()
|
|
19
|
-
.zIndex(5000)
|
|
20
|
-
.backgroundColor("var(--primary-bg, white)")
|
|
21
|
-
.color("var(--primary-color, darkgray)")
|
|
22
|
-
.left(0)
|
|
23
|
-
, "*[data-inline-popup=inline-popup]");
|
|
24
|
-
|
|
25
|
-
CSS(StyleRule()
|
|
26
|
-
.right(0)
|
|
27
|
-
.left("unset")
|
|
28
|
-
, "*[data-alignment=bottom-right] > [data-inline-popup=inline-popup]");
|
|
13
|
+
import "./styles/inline-popup-style";
|
|
29
14
|
|
|
30
15
|
function closeHandler(
|
|
31
16
|
opener: HTMLElement,
|