jsswift 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/AI.md +10 -2
- package/dist/documentions/AI.md +10 -2
- package/dist/documentions/components/dialog.md +4 -0
- package/dist/documentions/components/input.md +450 -45
- package/dist/documentions/components/select.md +441 -51
- package/dist/documentions/examples/crud.md +65 -0
- package/dist/documentions/knowledge-map.json +16 -1
- package/dist/jsswift.js +41 -2
- package/dist/jsswift.min.js +3 -3
- package/dist/min-jsswift.js +3 -3
- package/package.json +1 -1
package/dist/jsswift.js
CHANGED
|
@@ -648,7 +648,10 @@
|
|
|
648
648
|
|
|
649
649
|
// scroll lock + focus
|
|
650
650
|
if (opts.lockScroll) lockScroll();
|
|
651
|
-
if (opts.autoFocus !== false) setTimeout(() =>
|
|
651
|
+
if (opts.autoFocus !== false) setTimeout(() => {
|
|
652
|
+
// Respect focus deliberately assigned by an onOpen callback.
|
|
653
|
+
if (panel.isConnected && stack.get(id) === entry && !panel.contains(document.activeElement)) focusFirst(panel);
|
|
654
|
+
}, 0);
|
|
652
655
|
|
|
653
656
|
// positioning (for menus/tooltips)
|
|
654
657
|
const position = (nextOpts = null) => {
|
|
@@ -7510,6 +7513,7 @@ const unitCover = (v, name = 'size') => {
|
|
|
7510
7513
|
// props: { model: rod OR [get,set] signal OR plain, placeholder, type }
|
|
7511
7514
|
|
|
7512
7515
|
|
|
7516
|
+
let uiFieldMessageId = 0;
|
|
7513
7517
|
UI.FormField = (props = {}) => {
|
|
7514
7518
|
|
|
7515
7519
|
applyCommonProps(props);
|
|
@@ -7642,6 +7646,14 @@ const unitCover = (v, name = 'size') => {
|
|
|
7642
7646
|
return true;
|
|
7643
7647
|
};
|
|
7644
7648
|
let messageEl = null;
|
|
7649
|
+
const messageId = `jsswift-field-message-${++uiFieldMessageId}`;
|
|
7650
|
+
const syncDescription = () => {
|
|
7651
|
+
if (!controlEl?.setAttribute) return;
|
|
7652
|
+
const ids = [uiUnwrap(props.ariaDescribedBy), messageEl?.id].filter(Boolean).join(" ").trim();
|
|
7653
|
+
if (ids) controlEl.setAttribute("aria-describedby", [...new Set(ids.split(/\s+/))].join(" "));
|
|
7654
|
+
else controlEl.removeAttribute("aria-describedby");
|
|
7655
|
+
};
|
|
7656
|
+
wrap._syncDescription = syncDescription;
|
|
7645
7657
|
const renderMessage = () => {
|
|
7646
7658
|
const statusOrder = [
|
|
7647
7659
|
{ key: "error", value: resolveValue(props.error), slot: "errorMessage", className: "cms-error" },
|
|
@@ -7669,7 +7681,7 @@ const unitCover = (v, name = 'size') => {
|
|
|
7669
7681
|
? renderSlotToArray(slots, active.slot, ctx, active.value)
|
|
7670
7682
|
: [];
|
|
7671
7683
|
const nextEl = nodes.length
|
|
7672
|
-
? _.div({ class: active?.className }, ...nodes)
|
|
7684
|
+
? _.div({ id: messageId, class: active?.className }, ...nodes)
|
|
7673
7685
|
: null;
|
|
7674
7686
|
|
|
7675
7687
|
const stateKeys = ["error", "warning", "success", "note"];
|
|
@@ -7682,6 +7694,7 @@ const unitCover = (v, name = 'size') => {
|
|
|
7682
7694
|
wrap.appendChild(nextEl);
|
|
7683
7695
|
}
|
|
7684
7696
|
messageEl = nextEl;
|
|
7697
|
+
syncDescription();
|
|
7685
7698
|
};
|
|
7686
7699
|
|
|
7687
7700
|
// state updater
|
|
@@ -7823,6 +7836,30 @@ const unitCover = (v, name = 'size') => {
|
|
|
7823
7836
|
return el;
|
|
7824
7837
|
};
|
|
7825
7838
|
|
|
7839
|
+
// Public field attributes belong to the interactive control, not its wrapper.
|
|
7840
|
+
function uiConfigureFieldControl(field, control, props, native = false) {
|
|
7841
|
+
field.focus = (options) => control.focus(options);
|
|
7842
|
+
const set = (name, value) => {
|
|
7843
|
+
if (value == null || value === false) control.removeAttribute(name);
|
|
7844
|
+
else control.setAttribute(name, String(value));
|
|
7845
|
+
};
|
|
7846
|
+
JSswift.reactive.effect(() => {
|
|
7847
|
+
const label = uiUnwrap(props.ariaLabel) ?? (typeof props.label === "string" ? props.label : null);
|
|
7848
|
+
set("aria-label", label);
|
|
7849
|
+
set("aria-labelledby", uiUnwrap(props.ariaLabelledBy));
|
|
7850
|
+
field._syncDescription?.();
|
|
7851
|
+
const invalid = props.ariaInvalid == null ? !!uiUnwrap(props.error) : !!uiUnwrap(props.ariaInvalid);
|
|
7852
|
+
control.setAttribute("aria-invalid", String(invalid));
|
|
7853
|
+
const required = !!uiUnwrap(props.required);
|
|
7854
|
+
control.setAttribute("aria-required", String(required));
|
|
7855
|
+
if (native) {
|
|
7856
|
+
control.required = required;
|
|
7857
|
+
for (const name of ["min", "max", "step", "pattern", "minLength", "maxLength"])
|
|
7858
|
+
set(name.toLowerCase(), uiUnwrap(props[name]));
|
|
7859
|
+
}
|
|
7860
|
+
}, "UI.Field:controlAttributes");
|
|
7861
|
+
}
|
|
7862
|
+
|
|
7826
7863
|
UI.Input = (props = {}) => {
|
|
7827
7864
|
const slots = props.slots || {};
|
|
7828
7865
|
const fieldProps = {
|
|
@@ -7984,6 +8021,7 @@ const unitCover = (v, name = 'size') => {
|
|
|
7984
8021
|
|
|
7985
8022
|
// expose reference
|
|
7986
8023
|
field._input = input;
|
|
8024
|
+
uiConfigureFieldControl(field, input, props, true);
|
|
7987
8025
|
uiRegisterShortcode(input, props, {
|
|
7988
8026
|
isEnabled: () => !input.disabled,
|
|
7989
8027
|
action: () => uiFocusShortcutTarget(input, { selectText: !!props.selectOnShortcode })
|
|
@@ -9381,6 +9419,7 @@ const unitCover = (v, name = 'size') => {
|
|
|
9381
9419
|
// refresh has-value when value changes
|
|
9382
9420
|
JSswift.reactive.effect(() => { field._refresh?.(); }, "UI.Select:fieldRefresh");
|
|
9383
9421
|
|
|
9422
|
+
uiConfigureFieldControl(field, root, props);
|
|
9384
9423
|
field._select = root;
|
|
9385
9424
|
field._dispose = root._dispose;
|
|
9386
9425
|
JSswift._registerCleanup?.(field, field._dispose);
|