@jsswift/ui 1.0.48 → 1.0.50
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/min-ui.js +3 -3
- package/dist/ui.js +37 -1
- package/dist/ui.min.js +3 -3
- package/package.json +2 -2
- package/src/10-primitives-layout.js +37 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsswift/ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.50",
|
|
4
4
|
"description": "JSswift UI layer built on top of @jsswift/core",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,6 +38,6 @@
|
|
|
38
38
|
"src"
|
|
39
39
|
],
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@jsswift/core": "^1.0.
|
|
41
|
+
"@jsswift/core": "^1.0.50"
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -1092,6 +1092,7 @@
|
|
|
1092
1092
|
// props: { model: rod OR [get,set] signal OR plain, placeholder, type }
|
|
1093
1093
|
|
|
1094
1094
|
|
|
1095
|
+
let uiFieldMessageId = 0;
|
|
1095
1096
|
UI.FormField = (props = {}) => {
|
|
1096
1097
|
|
|
1097
1098
|
applyCommonProps(props);
|
|
@@ -1224,6 +1225,14 @@
|
|
|
1224
1225
|
return true;
|
|
1225
1226
|
};
|
|
1226
1227
|
let messageEl = null;
|
|
1228
|
+
const messageId = `jsswift-field-message-${++uiFieldMessageId}`;
|
|
1229
|
+
const syncDescription = () => {
|
|
1230
|
+
if (!controlEl?.setAttribute) return;
|
|
1231
|
+
const ids = [uiUnwrap(props.ariaDescribedBy), messageEl?.id].filter(Boolean).join(" ").trim();
|
|
1232
|
+
if (ids) controlEl.setAttribute("aria-describedby", [...new Set(ids.split(/\s+/))].join(" "));
|
|
1233
|
+
else controlEl.removeAttribute("aria-describedby");
|
|
1234
|
+
};
|
|
1235
|
+
wrap._syncDescription = syncDescription;
|
|
1227
1236
|
const renderMessage = () => {
|
|
1228
1237
|
const statusOrder = [
|
|
1229
1238
|
{ key: "error", value: resolveValue(props.error), slot: "errorMessage", className: "cms-error" },
|
|
@@ -1251,7 +1260,7 @@
|
|
|
1251
1260
|
? renderSlotToArray(slots, active.slot, ctx, active.value)
|
|
1252
1261
|
: [];
|
|
1253
1262
|
const nextEl = nodes.length
|
|
1254
|
-
? _.div({ class: active?.className }, ...nodes)
|
|
1263
|
+
? _.div({ id: messageId, class: active?.className }, ...nodes)
|
|
1255
1264
|
: null;
|
|
1256
1265
|
|
|
1257
1266
|
const stateKeys = ["error", "warning", "success", "note"];
|
|
@@ -1264,6 +1273,7 @@
|
|
|
1264
1273
|
wrap.appendChild(nextEl);
|
|
1265
1274
|
}
|
|
1266
1275
|
messageEl = nextEl;
|
|
1276
|
+
syncDescription();
|
|
1267
1277
|
};
|
|
1268
1278
|
|
|
1269
1279
|
// state updater
|
|
@@ -1405,6 +1415,30 @@
|
|
|
1405
1415
|
return el;
|
|
1406
1416
|
};
|
|
1407
1417
|
|
|
1418
|
+
// Public field attributes belong to the interactive control, not its wrapper.
|
|
1419
|
+
function uiConfigureFieldControl(field, control, props, native = false) {
|
|
1420
|
+
field.focus = (options) => control.focus(options);
|
|
1421
|
+
const set = (name, value) => {
|
|
1422
|
+
if (value == null || value === false) control.removeAttribute(name);
|
|
1423
|
+
else control.setAttribute(name, String(value));
|
|
1424
|
+
};
|
|
1425
|
+
JSswift.reactive.effect(() => {
|
|
1426
|
+
const label = uiUnwrap(props.ariaLabel) ?? (typeof props.label === "string" ? props.label : null);
|
|
1427
|
+
set("aria-label", label);
|
|
1428
|
+
set("aria-labelledby", uiUnwrap(props.ariaLabelledBy));
|
|
1429
|
+
field._syncDescription?.();
|
|
1430
|
+
const invalid = props.ariaInvalid == null ? !!uiUnwrap(props.error) : !!uiUnwrap(props.ariaInvalid);
|
|
1431
|
+
control.setAttribute("aria-invalid", String(invalid));
|
|
1432
|
+
const required = !!uiUnwrap(props.required);
|
|
1433
|
+
control.setAttribute("aria-required", String(required));
|
|
1434
|
+
if (native) {
|
|
1435
|
+
control.required = required;
|
|
1436
|
+
for (const name of ["min", "max", "step", "pattern", "minLength", "maxLength"])
|
|
1437
|
+
set(name.toLowerCase(), uiUnwrap(props[name]));
|
|
1438
|
+
}
|
|
1439
|
+
}, "UI.Field:controlAttributes");
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1408
1442
|
UI.Input = (props = {}) => {
|
|
1409
1443
|
const slots = props.slots || {};
|
|
1410
1444
|
const fieldProps = {
|
|
@@ -1566,6 +1600,7 @@
|
|
|
1566
1600
|
|
|
1567
1601
|
// expose reference
|
|
1568
1602
|
field._input = input;
|
|
1603
|
+
uiConfigureFieldControl(field, input, props, true);
|
|
1569
1604
|
uiRegisterShortcode(input, props, {
|
|
1570
1605
|
isEnabled: () => !input.disabled,
|
|
1571
1606
|
action: () => uiFocusShortcutTarget(input, { selectText: !!props.selectOnShortcode })
|
|
@@ -2963,6 +2998,7 @@
|
|
|
2963
2998
|
// refresh has-value when value changes
|
|
2964
2999
|
JSswift.reactive.effect(() => { field._refresh?.(); }, "UI.Select:fieldRefresh");
|
|
2965
3000
|
|
|
3001
|
+
uiConfigureFieldControl(field, root, props);
|
|
2966
3002
|
field._select = root;
|
|
2967
3003
|
field._dispose = root._dispose;
|
|
2968
3004
|
JSswift._registerCleanup?.(field, field._dispose);
|