@xeplr/ui-factory 1.0.13 → 1.1.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/AUTHORING.md +29 -5
- package/README.md +140 -18
- package/package.json +1 -1
- package/src/controls.js +19 -13
- package/src/designs/BuilderSample.jsx +77 -19
- package/src/designs/ControlView.jsx +10 -1
- package/src/designs/FlowRunnerSample.jsx +6 -4
- package/src/designs/ListView.jsx +40 -21
- package/src/designs/Palette.jsx +2 -1
- package/src/designs/PropertyPanel.jsx +57 -1
- package/src/designs/ScreenEditorSample.jsx +97 -0
- package/src/designs/ScreenModal.jsx +2 -2
- package/src/designs/ScreenSample.jsx +100 -41
- package/src/designs/factory.css +170 -76
- package/src/designs/index.js +4 -0
- package/src/designs/styles.js +11 -1
- package/src/generate.js +35 -10
- package/src/hooks.js +1 -1
- package/src/index.js +6 -2
- package/src/model.js +2 -1
- package/src/pages.jsx +15 -3
- package/src/presets.js +324 -0
- package/src/remote.js +7 -1
- package/src/scaffold.js +2 -2
- package/src/screenSource.js +91 -0
- package/src/tableSchema.js +109 -6
- package/src/useFactoryBuilder.js +65 -16
- package/src/useFactoryScreen.js +74 -39
- package/src/useScreenSource.js +81 -0
- package/src/validateDocument.js +5 -1
- package/src/values.js +18 -5
package/src/validateDocument.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { CONTROLS, LABEL_VARIANTS, LIST_ACTIONS, STYLE_KEYS, SCREEN_STYLE_KEYS, LAYOUTS, MULTI_SEPARATOR, MAX_FILE_MB, STEP_LIMIT, acceptList } from './controls.js'
|
|
14
14
|
import { DOCUMENT_KIND, DOCUMENT_VERSION } from './document.js'
|
|
15
15
|
import { RESERVED_COLUMNS, MAX_IDENTIFIER } from './tableSchema.js'
|
|
16
|
+
import { FIELD_PRESETS, INPUT_TYPES, presetFor } from './presets.js'
|
|
16
17
|
|
|
17
18
|
const FIELD_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/
|
|
18
19
|
const TABLE_NAME = /^[A-Za-z_][A-Za-z0-9_.$-]*$/
|
|
@@ -88,6 +89,9 @@ export function validateDocument(doc, controls = CONTROLS) {
|
|
|
88
89
|
if (!nonEmptyString(props.label)) err(`${at}.props.label`, 'is required — the text shown above the field')
|
|
89
90
|
if (props.required !== undefined && typeof props.required !== 'boolean') err(`${at}.props.required`, 'must be true or false')
|
|
90
91
|
if (props.placeholder !== undefined && typeof props.placeholder !== 'string') err(`${at}.props.placeholder`, 'must be a string')
|
|
92
|
+
// Where the field came from (a ready-made field's key), or false: plain on purpose.
|
|
93
|
+
if (props.preset !== undefined && props.preset !== false && !presetFor(props.preset)) err(`${at}.props.preset`, `"${props.preset}" is not a ready-made field — one of: ${FIELD_PRESETS.map((p) => p.key).join(', ')}, or false`)
|
|
94
|
+
if (props.inputType !== undefined && !INPUT_TYPES.includes(props.inputType)) err(`${at}.props.inputType`, `must be one of: ${INPUT_TYPES.join(', ')}`)
|
|
91
95
|
checkDefault(node, def, at, err)
|
|
92
96
|
checkValidation(node, def, at, err)
|
|
93
97
|
}
|
|
@@ -234,7 +238,7 @@ function checkValidation(node, def, at, err) {
|
|
|
234
238
|
const val = v[key]
|
|
235
239
|
if (key === 'minLength' || key === 'maxLength') {
|
|
236
240
|
if (!(Number.isInteger(val) && val >= 0)) err(path, 'must be a whole number, 0 or more')
|
|
237
|
-
} else if (key === 'integer') {
|
|
241
|
+
} else if (key === 'integer' || key === 'notFuture') {
|
|
238
242
|
if (typeof val !== 'boolean') err(path, 'must be true or false')
|
|
239
243
|
} else if (key === 'pattern') {
|
|
240
244
|
try { new RegExp(val) } catch (_) { err(path, `"${val}" is not a valid regular expression`) }
|
package/src/values.js
CHANGED
|
@@ -32,6 +32,13 @@ export function formSchema(doc, controls = CONTROLS) {
|
|
|
32
32
|
const v = p.validation && { ...p.validation }
|
|
33
33
|
if (v) {
|
|
34
34
|
delete v.patternMessage
|
|
35
|
+
// "Not in the future" is today's date AT THE MOMENT OF CHECKING — the
|
|
36
|
+
// server builds this schema per save, so it never goes stale.
|
|
37
|
+
if (v.notFuture) {
|
|
38
|
+
const today = localDay()
|
|
39
|
+
if (!v.max || v.max > today) v.max = today
|
|
40
|
+
}
|
|
41
|
+
delete v.notFuture
|
|
35
42
|
if (Object.keys(v).length) field.validation = v
|
|
36
43
|
}
|
|
37
44
|
return field
|
|
@@ -130,6 +137,7 @@ export function fieldError(node, value, loadedOptions) {
|
|
|
130
137
|
const day = value.slice(0, 10)
|
|
131
138
|
if (v.min && day < v.min) return `${label} must be on or after ${v.min}`
|
|
132
139
|
if (v.max && day > v.max) return `${label} must be on or before ${v.max}`
|
|
140
|
+
if (v.notFuture && day > localDay()) return `${label} cannot be in the future`
|
|
133
141
|
return null
|
|
134
142
|
}
|
|
135
143
|
case 'datetime': {
|
|
@@ -173,15 +181,20 @@ export function optionValue(options, raw) {
|
|
|
173
181
|
return hit ? hit.id : raw
|
|
174
182
|
}
|
|
175
183
|
|
|
184
|
+
/** Today as YYYY-MM-DD, in the local timezone — the day a person means by "today". */
|
|
185
|
+
function localDay() {
|
|
186
|
+
const d = new Date()
|
|
187
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
|
188
|
+
}
|
|
189
|
+
|
|
176
190
|
function safeRegExp(pattern) {
|
|
177
191
|
try { return new RegExp(pattern) } catch (_) { return { test: () => true } }
|
|
178
192
|
}
|
|
179
193
|
|
|
180
|
-
// ──
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
//
|
|
184
|
-
// empty — it only holds the save back.
|
|
194
|
+
// ── can it save? ─────────────────────────────────────────────────────────
|
|
195
|
+
// Save (a button, one AJAX call) goes out only when what is entered is
|
|
196
|
+
// acceptable. This decides whether it can, and which messages to SHOW: a field
|
|
197
|
+
// nobody has touched is not shouted at for being empty until Save is pressed.
|
|
185
198
|
|
|
186
199
|
/**
|
|
187
200
|
* @param touched Set of field names the person has changed or left
|