jedison 1.14.0 → 1.16.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/CHANGELOG.md +12 -0
- package/dist/cjs/jedison.cjs +1 -1
- package/dist/cjs/jedison.cjs.map +1 -1
- package/dist/esm/jedison.js +405 -83
- package/dist/esm/jedison.js.map +1 -1
- package/dist/umd/jedison.umd.js +1 -1
- package/dist/umd/jedison.umd.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/jedison.js
CHANGED
|
@@ -116,6 +116,36 @@ function getType(value) {
|
|
|
116
116
|
}
|
|
117
117
|
return type2;
|
|
118
118
|
}
|
|
119
|
+
const DEFAULT_ATTRIBUTE_ALLOWLIST = [
|
|
120
|
+
"id",
|
|
121
|
+
"class",
|
|
122
|
+
"title",
|
|
123
|
+
"name",
|
|
124
|
+
"value",
|
|
125
|
+
"disabled",
|
|
126
|
+
"always-enabled",
|
|
127
|
+
"always-disabled"
|
|
128
|
+
];
|
|
129
|
+
const DEFAULT_ATTRIBUTE_ALLOWED_PREFIXES = ["aria-", "data-"];
|
|
130
|
+
function filterAttributes(attributes, options = {}) {
|
|
131
|
+
const {
|
|
132
|
+
allowlist = DEFAULT_ATTRIBUTE_ALLOWLIST,
|
|
133
|
+
allowedPrefixes = DEFAULT_ATTRIBUTE_ALLOWED_PREFIXES
|
|
134
|
+
} = options;
|
|
135
|
+
const result = {};
|
|
136
|
+
if (!isObject(attributes)) {
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
const allowed = new Set(allowlist.map((name) => name.toLowerCase()));
|
|
140
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
141
|
+
const normalizedKey = key.trim().toLowerCase();
|
|
142
|
+
const isAllowed = allowed.has(normalizedKey) || allowedPrefixes.some((prefix) => normalizedKey.startsWith(prefix));
|
|
143
|
+
if (isAllowed) {
|
|
144
|
+
result[key] = value;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
119
149
|
const UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
120
150
|
function mergeDeep(target, ...sources) {
|
|
121
151
|
if (!sources.length) return target;
|
|
@@ -148,14 +178,14 @@ function combineDeep(target, ...sources) {
|
|
|
148
178
|
Object.keys(source).forEach((key) => {
|
|
149
179
|
if (UNSAFE_KEYS.has(key)) return;
|
|
150
180
|
if (isObject(source[key])) {
|
|
151
|
-
if (!target[key]) {
|
|
181
|
+
if (!isObject(target[key])) {
|
|
152
182
|
Object.assign(target, {
|
|
153
183
|
[key]: {}
|
|
154
184
|
});
|
|
155
185
|
}
|
|
156
186
|
combineDeep(target[key], source[key]);
|
|
157
187
|
} else if (Array.isArray(source[key])) {
|
|
158
|
-
if (!target[key]) {
|
|
188
|
+
if (!Array.isArray(target[key])) {
|
|
159
189
|
target[key] = [];
|
|
160
190
|
}
|
|
161
191
|
target[key].push(...source[key]);
|
|
@@ -430,6 +460,10 @@ function getSchemaXOption(schema, option) {
|
|
|
430
460
|
if (schema["x-options"] && isSet(schema["x-options"][option])) {
|
|
431
461
|
return schema["x-options"][option];
|
|
432
462
|
}
|
|
463
|
+
if (option === "switcherInput" && schema["x-embedSwitcher"] === true) {
|
|
464
|
+
console.warn(`Jedison: schema option "x-embedSwitcher" is deprecated. Use "x-switcherInput: 'select-inline'" instead.`);
|
|
465
|
+
return "select-inline";
|
|
466
|
+
}
|
|
433
467
|
for (const alias of getAliasesFor(option)) {
|
|
434
468
|
const xAlias = "x-" + alias;
|
|
435
469
|
if (isSet(schema[xAlias])) {
|
|
@@ -1778,8 +1812,28 @@ class EventEmitter {
|
|
|
1778
1812
|
}
|
|
1779
1813
|
callbacks.push(callback);
|
|
1780
1814
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1815
|
+
/**
|
|
1816
|
+
* Removes event listeners for a named event.
|
|
1817
|
+
* @public
|
|
1818
|
+
* @param {string} name - The name of the event
|
|
1819
|
+
* @param {function} [callback] - When given, only this specific callback is
|
|
1820
|
+
* removed; when omitted, all listeners for the event are removed.
|
|
1821
|
+
*/
|
|
1822
|
+
off(name, callback) {
|
|
1823
|
+
if (typeof callback !== "function") {
|
|
1824
|
+
this.listeners.delete(name);
|
|
1825
|
+
return;
|
|
1826
|
+
}
|
|
1827
|
+
const callbacks = this.listeners.get(name);
|
|
1828
|
+
if (!callbacks) {
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
const remaining = callbacks.filter((cb) => cb !== callback);
|
|
1832
|
+
if (remaining.length === 0) {
|
|
1833
|
+
this.listeners.delete(name);
|
|
1834
|
+
} else {
|
|
1835
|
+
this.listeners.set(name, remaining);
|
|
1836
|
+
}
|
|
1783
1837
|
}
|
|
1784
1838
|
/**
|
|
1785
1839
|
* Triggers the callback function of a named event listener
|
|
@@ -2145,6 +2199,7 @@ class Editor {
|
|
|
2145
2199
|
this.addEventListeners();
|
|
2146
2200
|
this.setVisibility();
|
|
2147
2201
|
this.setContainerAttributes();
|
|
2202
|
+
this.appendSchemaButtons();
|
|
2148
2203
|
this.refreshUI();
|
|
2149
2204
|
const alwaysShowErrors = this.instance.jedison.getOption("showErrors") === "always" || getSchemaXOption(this.instance.schema, "showErrors") === "always";
|
|
2150
2205
|
if (alwaysShowErrors) {
|
|
@@ -2158,6 +2213,14 @@ class Editor {
|
|
|
2158
2213
|
}
|
|
2159
2214
|
static resolves(schema) {
|
|
2160
2215
|
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Whether this editor already renders a heading for each of its children
|
|
2218
|
+
* (e.g. an accordion toggle or a nav tab label), so a child editor can
|
|
2219
|
+
* skip drawing its own duplicate heading/panel when embedded here.
|
|
2220
|
+
*/
|
|
2221
|
+
static providesChildHeading() {
|
|
2222
|
+
return false;
|
|
2223
|
+
}
|
|
2161
2224
|
/**
|
|
2162
2225
|
* Initializes the editor
|
|
2163
2226
|
*/
|
|
@@ -2200,6 +2263,62 @@ class Editor {
|
|
|
2200
2263
|
}
|
|
2201
2264
|
}
|
|
2202
2265
|
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Renders schema-defined action buttons (the `x-buttons` keyword) into the
|
|
2268
|
+
* editor container. Works for every editor because it lives on the base
|
|
2269
|
+
* class, next to setAttributes()/setContainerAttributes(). Both `x-buttons`
|
|
2270
|
+
* and `x-options.buttons` spellings resolve through getSchemaXOption().
|
|
2271
|
+
*
|
|
2272
|
+
* Security decisions from issue #62:
|
|
2273
|
+
* - The label is HTML sanitized through the existing DOMPurify pipeline
|
|
2274
|
+
* (purifyContent(), decision 9c / F6) before being handed to the theme.
|
|
2275
|
+
* - The `attributes` bag is filtered against an allowlist (filterAttributes(),
|
|
2276
|
+
* decision 6a / F1); `always-enabled` / `always-disabled` are intentionally
|
|
2277
|
+
* allowed (decision 6b, trusted-schema stance).
|
|
2278
|
+
* - Each button emits a `jedison:<name>` event on the root Jedison instance
|
|
2279
|
+
* through the internal EventEmitter (decision 1c / 2), carrying a live
|
|
2280
|
+
* payload `{ jedison, editor, path }` (decision 8). Consumers subscribe with
|
|
2281
|
+
* `jedison.on('jedison:<name>', ({ jedison, editor, path }) => ...)`. The
|
|
2282
|
+
* listener map is private to the instance, so the payload is not exposed to
|
|
2283
|
+
* unrelated scripts on the page (F3 contained).
|
|
2284
|
+
* - Click listeners are registered through storedEventListeners so destroy()
|
|
2285
|
+
* cleans them up.
|
|
2286
|
+
*/
|
|
2287
|
+
appendSchemaButtons() {
|
|
2288
|
+
const buttons = getSchemaXOption(this.instance.schema, "buttons");
|
|
2289
|
+
if (!isArray(buttons)) {
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
const domPurifyOptions = this.instance.jedison.getOption("domPurifyOptions");
|
|
2293
|
+
buttons.forEach((config) => {
|
|
2294
|
+
if (!isObject(config)) {
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
const rawLabel = isString(config.label) ? config.label : "";
|
|
2298
|
+
const label = this.purifyEnabled ? this.purifyContent(rawLabel, domPurifyOptions) : rawLabel;
|
|
2299
|
+
const attributes = filterAttributes(config.attributes);
|
|
2300
|
+
const button = this.theme.getXButton({ label, attributes });
|
|
2301
|
+
this.control.container.appendChild(button);
|
|
2302
|
+
const eventName = isObject(config.event) && isString(config.event.name) ? config.event.name : null;
|
|
2303
|
+
if (!eventName) {
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
const handler = () => {
|
|
2307
|
+
const jedison = this.instance.jedison;
|
|
2308
|
+
jedison.emit("jedison:" + eventName, {
|
|
2309
|
+
jedison,
|
|
2310
|
+
editor: this,
|
|
2311
|
+
path: this.instance.path
|
|
2312
|
+
});
|
|
2313
|
+
};
|
|
2314
|
+
button.addEventListener("click", handler);
|
|
2315
|
+
this.storedEventListeners.push({
|
|
2316
|
+
element: button,
|
|
2317
|
+
eventType: "click",
|
|
2318
|
+
handler
|
|
2319
|
+
});
|
|
2320
|
+
});
|
|
2321
|
+
}
|
|
2203
2322
|
/**
|
|
2204
2323
|
* Builds the editor control and appends it to the editor container
|
|
2205
2324
|
*/
|
|
@@ -2508,6 +2627,7 @@ class EditorIfThenElse extends Editor {
|
|
|
2508
2627
|
this.refreshDisabledState();
|
|
2509
2628
|
this.control.childrenSlot.innerHTML = "";
|
|
2510
2629
|
this.control.childrenSlot.appendChild(this.instance.activeInstance.ui.control.container);
|
|
2630
|
+
this.control.switcherSlot = this.instance.activeInstance.ui.control.switcherSlot;
|
|
2511
2631
|
if (this.disabled || this.instance.isReadOnly()) {
|
|
2512
2632
|
this.instance.activeInstance.ui.disable();
|
|
2513
2633
|
} else {
|
|
@@ -4131,7 +4251,7 @@ class EditorObject extends Editor {
|
|
|
4131
4251
|
return {
|
|
4132
4252
|
title: this.getTitle(),
|
|
4133
4253
|
description: this.getDescription(),
|
|
4134
|
-
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
4254
|
+
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden") ?? this.isEmbeddedInParentChrome(),
|
|
4135
4255
|
id: this.getIdFromPath(this.instance.path),
|
|
4136
4256
|
enablePropertiesToggle,
|
|
4137
4257
|
addProperty,
|
|
@@ -4147,9 +4267,20 @@ class EditorObject extends Editor {
|
|
|
4147
4267
|
titleIconClass: getSchemaXOption(this.instance.schema, "titleIconClass")
|
|
4148
4268
|
};
|
|
4149
4269
|
}
|
|
4270
|
+
isEmbeddedInParentChrome() {
|
|
4271
|
+
var _a;
|
|
4272
|
+
const autoFlat = getSchemaXOption(this.instance.schema, "autoFlat") ?? this.instance.jedison.getOption("autoFlat");
|
|
4273
|
+
if (!autoFlat) return false;
|
|
4274
|
+
const parentInstance = this.instance.parent;
|
|
4275
|
+
if (!parentInstance) return false;
|
|
4276
|
+
const ParentEditorClass = this.instance.jedison.uiResolver.getClass(parentInstance.schema);
|
|
4277
|
+
return !!((_a = ParentEditorClass == null ? void 0 : ParentEditorClass.providesChildHeading) == null ? void 0 : _a.call(ParentEditorClass));
|
|
4278
|
+
}
|
|
4150
4279
|
build() {
|
|
4151
4280
|
this.propertyActivators = {};
|
|
4152
|
-
const
|
|
4281
|
+
const explicitCard = getSchemaXOption(this.instance.schema, "card");
|
|
4282
|
+
const globalCard = this.instance.jedison.getOption("card");
|
|
4283
|
+
const card = explicitCard ?? (this.isEmbeddedInParentChrome() ? false : globalCard);
|
|
4153
4284
|
const config = this.getObjectControlConfig();
|
|
4154
4285
|
this.control = card === false ? this.theme.getObjectControlFlat(config) : this.theme.getObjectControl(config);
|
|
4155
4286
|
this.control.jsonData.input.value = JSON.stringify(this.instance.getValue(), null, 2);
|
|
@@ -4400,6 +4531,7 @@ class EditorObjectCategories extends EditorObject {
|
|
|
4400
4531
|
init() {
|
|
4401
4532
|
super.init();
|
|
4402
4533
|
this.activeCategoryName = null;
|
|
4534
|
+
this.userSelectedCategory = false;
|
|
4403
4535
|
}
|
|
4404
4536
|
navigateTo(path) {
|
|
4405
4537
|
const nextChildPath = this.getNextChildPath(path);
|
|
@@ -4419,6 +4551,7 @@ class EditorObjectCategories extends EditorObject {
|
|
|
4419
4551
|
categoryName = defaultLabel;
|
|
4420
4552
|
}
|
|
4421
4553
|
this.activeCategoryName = categoryName;
|
|
4554
|
+
this.userSelectedCategory = true;
|
|
4422
4555
|
this.refreshUI();
|
|
4423
4556
|
}
|
|
4424
4557
|
}
|
|
@@ -4469,9 +4602,6 @@ class EditorObjectCategories extends EditorObject {
|
|
|
4469
4602
|
}
|
|
4470
4603
|
categoriesMap.get(categoryName).children.push(child);
|
|
4471
4604
|
});
|
|
4472
|
-
if (!categoriesMap.has(this.activeCategoryName)) {
|
|
4473
|
-
this.activeCategoryName = categoriesMap.keys().next().value;
|
|
4474
|
-
}
|
|
4475
4605
|
const categoryOrder = getSchemaXOption(this.instance.schema, "categoryOrder");
|
|
4476
4606
|
const allNames = Array.from(categoriesMap.keys());
|
|
4477
4607
|
let orderedCategoryNames = allNames;
|
|
@@ -4480,6 +4610,9 @@ class EditorObjectCategories extends EditorObject {
|
|
|
4480
4610
|
const unspecified = allNames.filter((name) => !categoryOrder.includes(name));
|
|
4481
4611
|
orderedCategoryNames = [...specifiedFirst, ...unspecified];
|
|
4482
4612
|
}
|
|
4613
|
+
if (!this.userSelectedCategory || !categoriesMap.has(this.activeCategoryName)) {
|
|
4614
|
+
this.activeCategoryName = orderedCategoryNames[0];
|
|
4615
|
+
}
|
|
4483
4616
|
orderedCategoryNames.forEach((categoryName) => {
|
|
4484
4617
|
const category = categoriesMap.get(categoryName);
|
|
4485
4618
|
const active = categoryName === this.activeCategoryName;
|
|
@@ -4494,6 +4627,7 @@ class EditorObjectCategories extends EditorObject {
|
|
|
4494
4627
|
});
|
|
4495
4628
|
tab.list.addEventListener("click", () => {
|
|
4496
4629
|
this.activeCategoryName = categoryName;
|
|
4630
|
+
this.userSelectedCategory = true;
|
|
4497
4631
|
});
|
|
4498
4632
|
const pane = document.createElement("div");
|
|
4499
4633
|
this.theme.setTabPaneAttributes(pane, active, id);
|
|
@@ -4517,6 +4651,9 @@ class EditorObjectNav extends EditorObject {
|
|
|
4517
4651
|
const hasNavFormat = regex.test(format2);
|
|
4518
4652
|
return getSchemaType(schema) === "object" && hasNavFormat;
|
|
4519
4653
|
}
|
|
4654
|
+
static providesChildHeading() {
|
|
4655
|
+
return true;
|
|
4656
|
+
}
|
|
4520
4657
|
init() {
|
|
4521
4658
|
super.init();
|
|
4522
4659
|
this.activeTabIndex = 0;
|
|
@@ -4603,11 +4740,35 @@ class EditorObjectAccordion extends EditorObject {
|
|
|
4603
4740
|
static resolves(schema) {
|
|
4604
4741
|
return getSchemaType(schema) === "object" && getSchemaXOption(schema, "format") === "accordion";
|
|
4605
4742
|
}
|
|
4743
|
+
static providesChildHeading() {
|
|
4744
|
+
return true;
|
|
4745
|
+
}
|
|
4606
4746
|
getObjectControlConfig() {
|
|
4607
4747
|
return { ...super.getObjectControlConfig(), isAccordionProperties: true };
|
|
4608
4748
|
}
|
|
4749
|
+
refreshAccordionWarnings() {
|
|
4750
|
+
if (!this.accordionToggles) return;
|
|
4751
|
+
const navWarning = getSchemaXOption(this.instance.schema, "navWarning") ?? true;
|
|
4752
|
+
const navWarningMessage = getSchemaXOption(this.instance.schema, "navWarningMessage");
|
|
4753
|
+
this.instance.children.forEach((child) => {
|
|
4754
|
+
if (!child.isActive) return;
|
|
4755
|
+
const toggle = this.accordionToggles[child.getKey()];
|
|
4756
|
+
if (!toggle) return;
|
|
4757
|
+
const existing = toggle.querySelector(".jedi-legend-warning");
|
|
4758
|
+
if (existing) existing.parentNode.removeChild(existing);
|
|
4759
|
+
if (navWarning && child.hasNestedValidationErrors()) {
|
|
4760
|
+
const warning = document.createElement("span");
|
|
4761
|
+
warning.classList.add("jedi-legend-warning");
|
|
4762
|
+
warning.textContent = "⚠";
|
|
4763
|
+
if (navWarningMessage) warning.setAttribute("title", navWarningMessage);
|
|
4764
|
+
this.theme.styleLegendWarning(warning);
|
|
4765
|
+
toggle.appendChild(warning);
|
|
4766
|
+
}
|
|
4767
|
+
});
|
|
4768
|
+
}
|
|
4609
4769
|
refreshEditors() {
|
|
4610
4770
|
this.control.childrenSlot.replaceChildren();
|
|
4771
|
+
this.accordionToggles = {};
|
|
4611
4772
|
const accordionId = this.control.childrenSlot.id;
|
|
4612
4773
|
this.instance.children.forEach((child) => {
|
|
4613
4774
|
if (!child.isActive) return;
|
|
@@ -4617,12 +4778,18 @@ class EditorObjectAccordion extends EditorObject {
|
|
|
4617
4778
|
const accordionItem = this.theme.getAccordionItem({ title, id, accordionId });
|
|
4618
4779
|
accordionItem.body.appendChild(child.ui.control.container);
|
|
4619
4780
|
this.control.childrenSlot.appendChild(accordionItem.container);
|
|
4781
|
+
this.accordionToggles[child.getKey()] = accordionItem.toggle;
|
|
4620
4782
|
if (this.disabled || this.instance.isReadOnly()) {
|
|
4621
4783
|
child.ui.disable();
|
|
4622
4784
|
} else {
|
|
4623
4785
|
child.ui.enable();
|
|
4624
4786
|
}
|
|
4625
4787
|
});
|
|
4788
|
+
this.refreshAccordionWarnings();
|
|
4789
|
+
}
|
|
4790
|
+
showValidationErrors(errors, force = false) {
|
|
4791
|
+
super.showValidationErrors(errors, force);
|
|
4792
|
+
this.refreshAccordionWarnings();
|
|
4626
4793
|
}
|
|
4627
4794
|
}
|
|
4628
4795
|
class EditorObjectHorizontal extends EditorObject {
|
|
@@ -5443,6 +5610,9 @@ class EditorArrayNav extends EditorArray {
|
|
|
5443
5610
|
const hasNavFormat = regex.test(format2);
|
|
5444
5611
|
return getSchemaType(schema) === "array" && hasNavFormat;
|
|
5445
5612
|
}
|
|
5613
|
+
static providesChildHeading() {
|
|
5614
|
+
return true;
|
|
5615
|
+
}
|
|
5446
5616
|
navigateTo(path) {
|
|
5447
5617
|
const nextChildPath = this.getNextChildPath(path);
|
|
5448
5618
|
if (nextChildPath) {
|
|
@@ -5597,7 +5767,7 @@ class EditorMultiple extends Editor {
|
|
|
5597
5767
|
}
|
|
5598
5768
|
build() {
|
|
5599
5769
|
this.switcherInput = getSchemaXOption(this.instance.schema, "switcherInput") ?? this.instance.jedison.getOption("switcherInput");
|
|
5600
|
-
this.embedSwitcher =
|
|
5770
|
+
this.embedSwitcher = this.instance.jedison.getOption("embedSwitcher");
|
|
5601
5771
|
this.control = this.theme.getMultipleControl({
|
|
5602
5772
|
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
5603
5773
|
id: this.getIdFromPath(this.instance.path),
|
|
@@ -5609,6 +5779,7 @@ class EditorMultiple extends Editor {
|
|
|
5609
5779
|
if (this.embedSwitcher) {
|
|
5610
5780
|
this.control.header.style.display = "none";
|
|
5611
5781
|
}
|
|
5782
|
+
this.switcherWrapper = this.theme.getSwitcherOwner();
|
|
5612
5783
|
this.instance.on("change", (initiator) => {
|
|
5613
5784
|
if (initiator === "api") return;
|
|
5614
5785
|
const jedison = this.instance.jedison;
|
|
@@ -5655,40 +5826,36 @@ class EditorMultiple extends Editor {
|
|
|
5655
5826
|
});
|
|
5656
5827
|
});
|
|
5657
5828
|
}
|
|
5829
|
+
if (this.switcherInput === "select-inline") {
|
|
5830
|
+
this.control.switcher.input.addEventListener("change", () => {
|
|
5831
|
+
const index2 = Number(this.control.switcher.input.value);
|
|
5832
|
+
this.instance.switchInstance(index2, void 0, "user");
|
|
5833
|
+
});
|
|
5834
|
+
}
|
|
5658
5835
|
}
|
|
5659
5836
|
refreshUI() {
|
|
5660
|
-
var _a;
|
|
5661
5837
|
this.refreshDisabledState();
|
|
5662
5838
|
this.control.childrenSlot.innerHTML = "";
|
|
5663
5839
|
this.control.childrenSlot.appendChild(this.instance.activeInstance.ui.control.container);
|
|
5664
|
-
|
|
5665
|
-
|
|
5840
|
+
const slot = this.instance.activeInstance.ui.control.switcherSlot;
|
|
5841
|
+
this.control.switcherSlot = slot;
|
|
5842
|
+
if (this.embedSwitcher || this.switcherInput === "modal" || this.switcherInput === "select-inline") {
|
|
5666
5843
|
if (slot) {
|
|
5667
|
-
|
|
5668
|
-
|
|
5844
|
+
this.switcherWrapper.innerHTML = "";
|
|
5845
|
+
this.switcherWrapper.appendChild(this.control.switcher.container);
|
|
5846
|
+
this.insertBySwitcherDepth(slot, this.switcherWrapper, this.getNestedSwitcherDepth(this.instance.activeInstance));
|
|
5669
5847
|
this.control.header.style.display = "none";
|
|
5670
5848
|
} else {
|
|
5671
5849
|
this.control.header.style.display = "";
|
|
5672
5850
|
this.control.header.appendChild(this.control.switcher.container);
|
|
5673
5851
|
}
|
|
5674
5852
|
}
|
|
5675
|
-
if (this.switcherInput === "modal") {
|
|
5676
|
-
const childControl = this.instance.activeInstance.ui.control;
|
|
5677
|
-
const infoContainer = childControl.infoContainer;
|
|
5678
|
-
const titleEl = childControl.legendText || childControl.label;
|
|
5679
|
-
if (infoContainer) {
|
|
5680
|
-
infoContainer.after(this.control.switcher.container);
|
|
5681
|
-
this.control.header.style.display = "none";
|
|
5682
|
-
} else if (titleEl) {
|
|
5683
|
-
const infoEl = (_a = childControl.info) == null ? void 0 : _a.container;
|
|
5684
|
-
const anchor = infoEl && infoEl.parentNode ? infoEl : titleEl;
|
|
5685
|
-
anchor.after(this.control.switcher.container);
|
|
5686
|
-
this.control.header.style.display = "none";
|
|
5687
|
-
}
|
|
5688
|
-
}
|
|
5689
5853
|
if (this.switcherInput === "select") {
|
|
5690
5854
|
this.control.switcher.input.value = this.instance.index;
|
|
5691
5855
|
}
|
|
5856
|
+
if (this.switcherInput === "select-inline") {
|
|
5857
|
+
this.control.switcher.input.value = this.instance.index;
|
|
5858
|
+
}
|
|
5692
5859
|
if (this.switcherInput === "radios" || this.switcherInput === "radios-inline") {
|
|
5693
5860
|
this.control.switcher.radios.forEach((radio) => {
|
|
5694
5861
|
const radioIndex = Number(radio.value);
|
|
@@ -5710,6 +5877,23 @@ class EditorMultiple extends Editor {
|
|
|
5710
5877
|
getErrorFeedback(config) {
|
|
5711
5878
|
return this.theme.getAlert(config);
|
|
5712
5879
|
}
|
|
5880
|
+
// Counts how many EditorMultiple owners sit between `instance` and the real
|
|
5881
|
+
// leaf control, so stacked switchers in a shared slot can be ordered
|
|
5882
|
+
// outer-first instead of shuffling with every refresh.
|
|
5883
|
+
getNestedSwitcherDepth(instance) {
|
|
5884
|
+
if (!instance || !instance.activeInstance) return 0;
|
|
5885
|
+
const childDepth = this.getNestedSwitcherDepth(instance.activeInstance);
|
|
5886
|
+
return instance.ui.switcherWrapper ? childDepth + 1 : childDepth;
|
|
5887
|
+
}
|
|
5888
|
+
insertBySwitcherDepth(slot, wrapper, depth) {
|
|
5889
|
+
wrapper.dataset.switcherDepth = depth;
|
|
5890
|
+
const sibling = Array.from(slot.children).find((child) => Number(child.dataset.switcherDepth) < depth);
|
|
5891
|
+
if (sibling) {
|
|
5892
|
+
slot.insertBefore(wrapper, sibling);
|
|
5893
|
+
} else {
|
|
5894
|
+
slot.appendChild(wrapper);
|
|
5895
|
+
}
|
|
5896
|
+
}
|
|
5713
5897
|
}
|
|
5714
5898
|
class EditorNull extends Editor {
|
|
5715
5899
|
static resolves(schema) {
|
|
@@ -6293,37 +6477,24 @@ class EditorArrayCheckboxes extends Editor {
|
|
|
6293
6477
|
const values = this.getEnumSourceValues();
|
|
6294
6478
|
const schemaItems = this.instance.schema.items || {};
|
|
6295
6479
|
const titles = getSchemaXOption(schemaItems, "enumTitles") || values;
|
|
6296
|
-
const id = this.getIdFromPath(this.instance.path);
|
|
6297
|
-
const messagesId = id + "-messages";
|
|
6298
|
-
const descriptionId = id + "-description";
|
|
6299
|
-
const describedBy = messagesId + " " + descriptionId;
|
|
6300
6480
|
this.control.checkboxControls.forEach((cc) => {
|
|
6301
6481
|
if (cc.parentNode) cc.parentNode.removeChild(cc);
|
|
6302
6482
|
});
|
|
6303
|
-
this.
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
label.setAttribute("for", checkboxId);
|
|
6319
|
-
labelText.textContent = titles && titles[index2] !== void 0 ? titles[index2] : value;
|
|
6320
|
-
checkboxControl.appendChild(checkbox);
|
|
6321
|
-
checkboxControl.appendChild(label);
|
|
6322
|
-
label.appendChild(labelText);
|
|
6323
|
-
this.control.checkboxes.push(checkbox);
|
|
6324
|
-
this.control.labels.push(label);
|
|
6325
|
-
this.control.labelTexts.push(labelText);
|
|
6326
|
-
this.control.checkboxControls.push(checkboxControl);
|
|
6483
|
+
const rebuilt = this.theme.getCheckboxesControl({
|
|
6484
|
+
title: this.getTitle(),
|
|
6485
|
+
description: this.getDescription(),
|
|
6486
|
+
values,
|
|
6487
|
+
titles,
|
|
6488
|
+
id: this.getIdFromPath(this.instance.path),
|
|
6489
|
+
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
6490
|
+
inline: getSchemaXOption(this.instance.schema, "format") === "checkboxes-inline",
|
|
6491
|
+
info: this.getInfo()
|
|
6492
|
+
});
|
|
6493
|
+
this.control.checkboxes = rebuilt.checkboxes;
|
|
6494
|
+
this.control.labels = rebuilt.labels;
|
|
6495
|
+
this.control.labelTexts = rebuilt.labelTexts;
|
|
6496
|
+
this.control.checkboxControls = rebuilt.checkboxControls;
|
|
6497
|
+
this.control.checkboxControls.forEach((checkboxControl) => {
|
|
6327
6498
|
this.control.fieldset.insertBefore(checkboxControl, this.control.description);
|
|
6328
6499
|
});
|
|
6329
6500
|
this.addDragHandles();
|
|
@@ -6973,6 +7144,7 @@ class Jedison extends EventEmitter {
|
|
|
6973
7144
|
editJsonData: false,
|
|
6974
7145
|
enablePropertiesToggle: false,
|
|
6975
7146
|
enableCollapseToggle: false,
|
|
7147
|
+
autoFlat: false,
|
|
6976
7148
|
btnContents: true,
|
|
6977
7149
|
btnIcons: true,
|
|
6978
7150
|
arrayDelete: true,
|
|
@@ -7298,6 +7470,20 @@ class Jedison extends EventEmitter {
|
|
|
7298
7470
|
}
|
|
7299
7471
|
});
|
|
7300
7472
|
}
|
|
7473
|
+
if (this.isEditor) {
|
|
7474
|
+
const schemaTypeArray = getSchemaType(config.schema);
|
|
7475
|
+
if (isArray(schemaTypeArray)) {
|
|
7476
|
+
const inferTypeSource = getSchemaXOption(config.schema, "inferType");
|
|
7477
|
+
if (isSet(inferTypeSource)) {
|
|
7478
|
+
const siblingPath = resolveInstancePath(config.path, inferTypeSource);
|
|
7479
|
+
const siblingInstance = this.getInstance(siblingPath);
|
|
7480
|
+
const siblingValue = siblingInstance ? siblingInstance.getValue() : void 0;
|
|
7481
|
+
if (isSet(siblingValue) && schemaTypeArray.includes(siblingValue)) {
|
|
7482
|
+
config.schema = { ...config.schema, type: siblingValue };
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
}
|
|
7486
|
+
}
|
|
7301
7487
|
const schemaOneOf = getSchemaOneOf(config.schema);
|
|
7302
7488
|
const schemaAnyOf = getSchemaAnyOf(config.schema);
|
|
7303
7489
|
const schemaIf = getSchemaIf(config.schema);
|
|
@@ -7877,6 +8063,25 @@ class Theme {
|
|
|
7877
8063
|
html.classList.add("jedi-children-slot");
|
|
7878
8064
|
return html;
|
|
7879
8065
|
}
|
|
8066
|
+
/**
|
|
8067
|
+
* Wrapper used by EditorMultiple to embed an inline switcher next to a control's title
|
|
8068
|
+
*/
|
|
8069
|
+
getSwitcherSlot() {
|
|
8070
|
+
const html = document.createElement("span");
|
|
8071
|
+
html.classList.add("jedi-switcher-slot");
|
|
8072
|
+
return html;
|
|
8073
|
+
}
|
|
8074
|
+
/**
|
|
8075
|
+
* Per-owner wrapper inside a switcherSlot — lets more than one EditorMultiple
|
|
8076
|
+
* embed a switcher into the same slot (e.g. nested anyOf/oneOf) without one
|
|
8077
|
+
* overwriting the other.
|
|
8078
|
+
*/
|
|
8079
|
+
getSwitcherOwner() {
|
|
8080
|
+
const html = document.createElement("span");
|
|
8081
|
+
html.classList.add("jedi-switcher-owner");
|
|
8082
|
+
html.style.marginInlineStart = "0.25rem";
|
|
8083
|
+
return html;
|
|
8084
|
+
}
|
|
7880
8085
|
/**
|
|
7881
8086
|
* Wrapper for error messages
|
|
7882
8087
|
*/
|
|
@@ -8141,6 +8346,42 @@ class Theme {
|
|
|
8141
8346
|
button.appendChild(text);
|
|
8142
8347
|
return button;
|
|
8143
8348
|
}
|
|
8349
|
+
/**
|
|
8350
|
+
* A schema-defined action button (x-buttons keyword).
|
|
8351
|
+
*
|
|
8352
|
+
* This method only renders: the label is expected to be already sanitized by
|
|
8353
|
+
* the editor (Editor.purifyContent(), decision 9c) and the attributes are
|
|
8354
|
+
* expected to be already filtered against the allowlist by the editor
|
|
8355
|
+
* (utils.filterAttributes(), decision 6a). The theme does not sanitize or
|
|
8356
|
+
* filter. No theme styling is applied, only the unstyled `jedi-x-button` hook
|
|
8357
|
+
* class (decision 4).
|
|
8358
|
+
* @param {object} config - Button config
|
|
8359
|
+
* @param {string} [config.label] - Pre-sanitized HTML label
|
|
8360
|
+
* @param {object} [config.attributes] - Pre-filtered HTML attributes
|
|
8361
|
+
* @return {HTMLButtonElement}
|
|
8362
|
+
*/
|
|
8363
|
+
getXButton(config = {}) {
|
|
8364
|
+
const button = document.createElement("button");
|
|
8365
|
+
const label = document.createElement("span");
|
|
8366
|
+
button.classList.add("jedi-x-button");
|
|
8367
|
+
button.setAttribute("type", "button");
|
|
8368
|
+
label.classList.add("jedi-x-button-label");
|
|
8369
|
+
label.innerHTML = config.label ?? "";
|
|
8370
|
+
button.appendChild(label);
|
|
8371
|
+
const attributes = isObject(config.attributes) ? config.attributes : {};
|
|
8372
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
8373
|
+
if (key === "class") {
|
|
8374
|
+
String(value).split(" ").forEach((cls) => {
|
|
8375
|
+
if (cls) {
|
|
8376
|
+
button.classList.add(cls);
|
|
8377
|
+
}
|
|
8378
|
+
});
|
|
8379
|
+
} else {
|
|
8380
|
+
button.setAttribute(key, value);
|
|
8381
|
+
}
|
|
8382
|
+
}
|
|
8383
|
+
return button;
|
|
8384
|
+
}
|
|
8144
8385
|
getAddPropertyButton(config) {
|
|
8145
8386
|
const html = this.getButton(config);
|
|
8146
8387
|
html.classList.add("jedi-add-property-btn");
|
|
@@ -8336,6 +8577,7 @@ class Theme {
|
|
|
8336
8577
|
const messages = this.getMessagesSlot({
|
|
8337
8578
|
id: messagesId
|
|
8338
8579
|
});
|
|
8580
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
8339
8581
|
if (((_a = config == null ? void 0 : config.info) == null ? void 0 : _a.variant) === "modal") {
|
|
8340
8582
|
this.infoAsModal(info, config.id, config.info);
|
|
8341
8583
|
}
|
|
@@ -8343,11 +8585,12 @@ class Theme {
|
|
|
8343
8585
|
if (isObject(config.info)) {
|
|
8344
8586
|
container.appendChild(info.container);
|
|
8345
8587
|
}
|
|
8588
|
+
container.appendChild(switcherSlot);
|
|
8346
8589
|
container.appendChild(placeholder);
|
|
8347
8590
|
container.appendChild(description);
|
|
8348
8591
|
container.appendChild(messages);
|
|
8349
8592
|
container.appendChild(actions);
|
|
8350
|
-
return { container, placeholder, label, info, labelText, description, messages, actions };
|
|
8593
|
+
return { container, placeholder, label, info, labelText, description, messages, actions, switcherSlot };
|
|
8351
8594
|
}
|
|
8352
8595
|
/**
|
|
8353
8596
|
* Object control is a card containing multiple editors.
|
|
@@ -8413,7 +8656,7 @@ class Theme {
|
|
|
8413
8656
|
propertiesContainer: quickAddPropertyContainer
|
|
8414
8657
|
});
|
|
8415
8658
|
const fieldset = this.getFieldset();
|
|
8416
|
-
const { legend, infoContainer, legendText, right } = this.getLegend({
|
|
8659
|
+
const { legend, left, infoContainer, legendText, right } = this.getLegend({
|
|
8417
8660
|
content: config.title,
|
|
8418
8661
|
id: config.id,
|
|
8419
8662
|
titleHidden: config.titleHidden,
|
|
@@ -8444,10 +8687,9 @@ class Theme {
|
|
|
8444
8687
|
body.appendChild(description);
|
|
8445
8688
|
}
|
|
8446
8689
|
body.appendChild(messages);
|
|
8447
|
-
const switcherSlot =
|
|
8448
|
-
|
|
8690
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
8691
|
+
left.appendChild(switcherSlot);
|
|
8449
8692
|
if (config.readOnly === false) {
|
|
8450
|
-
right.appendChild(switcherSlot);
|
|
8451
8693
|
right.appendChild(actions);
|
|
8452
8694
|
}
|
|
8453
8695
|
body.appendChild(childrenSlot);
|
|
@@ -8502,6 +8744,9 @@ class Theme {
|
|
|
8502
8744
|
const ariaLive = this.getPropertiesAriaLive();
|
|
8503
8745
|
const messages = this.getMessagesSlot();
|
|
8504
8746
|
const childrenSlot = this.getChildrenSlot();
|
|
8747
|
+
if (config.isAccordion || config.isAccordionProperties) {
|
|
8748
|
+
childrenSlot.id = "accordion-" + config.id;
|
|
8749
|
+
}
|
|
8505
8750
|
const propertiesActivators = this.getPropertiesActivators();
|
|
8506
8751
|
const info = this.getInfo(config.info);
|
|
8507
8752
|
const description = this.getDescription({ content: config.description });
|
|
@@ -8528,8 +8773,7 @@ class Theme {
|
|
|
8528
8773
|
const collapse = document.createElement("div");
|
|
8529
8774
|
const collapseToggle = document.createElement("div");
|
|
8530
8775
|
const infoContainer = document.createElement("div");
|
|
8531
|
-
const switcherSlot =
|
|
8532
|
-
switcherSlot.classList.add("jedi-switcher-slot");
|
|
8776
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
8533
8777
|
const legend = document.createElement("div");
|
|
8534
8778
|
legend.classList.add("jedi-editor-legend");
|
|
8535
8779
|
legend.style.display = "flex";
|
|
@@ -8550,6 +8794,7 @@ class Theme {
|
|
|
8550
8794
|
this.visuallyHidden(legendText);
|
|
8551
8795
|
}
|
|
8552
8796
|
left.appendChild(legendText);
|
|
8797
|
+
left.appendChild(switcherSlot);
|
|
8553
8798
|
if (((_a = config == null ? void 0 : config.info) == null ? void 0 : _a.variant) === "modal") {
|
|
8554
8799
|
this.infoAsModal(info, config.id, config.info);
|
|
8555
8800
|
}
|
|
@@ -8558,8 +8803,6 @@ class Theme {
|
|
|
8558
8803
|
}
|
|
8559
8804
|
const innerWrapper = document.createElement("div");
|
|
8560
8805
|
innerWrapper.appendChild(legend);
|
|
8561
|
-
innerWrapper.appendChild(propertiesContainer);
|
|
8562
|
-
innerWrapper.appendChild(quickAddPropertyContainer);
|
|
8563
8806
|
container.appendChild(innerWrapper);
|
|
8564
8807
|
if (config.addProperty) {
|
|
8565
8808
|
quickAddPropertyContainer.appendChild(quickAddPropertyControl.container);
|
|
@@ -8570,11 +8813,12 @@ class Theme {
|
|
|
8570
8813
|
}
|
|
8571
8814
|
body.appendChild(messages);
|
|
8572
8815
|
if (config.readOnly === false) {
|
|
8573
|
-
right.appendChild(switcherSlot);
|
|
8574
8816
|
right.appendChild(actions);
|
|
8575
8817
|
}
|
|
8576
8818
|
body.appendChild(childrenSlot);
|
|
8577
8819
|
innerWrapper.appendChild(body);
|
|
8820
|
+
innerWrapper.appendChild(propertiesContainer);
|
|
8821
|
+
innerWrapper.appendChild(quickAddPropertyContainer);
|
|
8578
8822
|
if (config.editJsonData) {
|
|
8579
8823
|
actions.appendChild(jsonData.toggle);
|
|
8580
8824
|
}
|
|
@@ -8667,8 +8911,11 @@ class Theme {
|
|
|
8667
8911
|
chevron.style.display = "inline-block";
|
|
8668
8912
|
chevron.style.transition = "transform 0.1s ease";
|
|
8669
8913
|
chevron.style.marginRight = "0.5em";
|
|
8914
|
+
const titleSpan = document.createElement("span");
|
|
8915
|
+
titleSpan.style.marginRight = "0.5em";
|
|
8916
|
+
titleSpan.textContent = config.title;
|
|
8670
8917
|
toggle.appendChild(chevron);
|
|
8671
|
-
toggle.appendChild(
|
|
8918
|
+
toggle.appendChild(titleSpan);
|
|
8672
8919
|
const collapse = document.createElement("div");
|
|
8673
8920
|
collapse.classList.add("jedi-accordion-collapse");
|
|
8674
8921
|
collapse.style.display = "none";
|
|
@@ -8721,7 +8968,7 @@ class Theme {
|
|
|
8721
8968
|
const footer = this.getArrayFooter();
|
|
8722
8969
|
const fieldset = this.getFieldset();
|
|
8723
8970
|
const info = this.getInfo(config.info);
|
|
8724
|
-
const { legend, legendText, infoContainer, right } = this.getLegend({
|
|
8971
|
+
const { legend, left, legendText, infoContainer, right } = this.getLegend({
|
|
8725
8972
|
content: config.title,
|
|
8726
8973
|
id: config.id,
|
|
8727
8974
|
titleHidden: config.titleHidden,
|
|
@@ -8764,10 +9011,9 @@ class Theme {
|
|
|
8764
9011
|
body.appendChild(description);
|
|
8765
9012
|
}
|
|
8766
9013
|
body.appendChild(messages);
|
|
8767
|
-
const switcherSlot =
|
|
8768
|
-
|
|
9014
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
9015
|
+
left.appendChild(switcherSlot);
|
|
8769
9016
|
if (config.readOnly === false) {
|
|
8770
|
-
right.appendChild(switcherSlot);
|
|
8771
9017
|
right.appendChild(actions);
|
|
8772
9018
|
}
|
|
8773
9019
|
actions.appendChild(btnGroup);
|
|
@@ -8851,7 +9097,7 @@ class Theme {
|
|
|
8851
9097
|
const messages = this.getMessagesSlot();
|
|
8852
9098
|
const childrenSlot = this.getChildrenSlot();
|
|
8853
9099
|
const randomId = generateRandomID(5);
|
|
8854
|
-
const knownSwitchers = ["select", "radios", "radios-inline", "modal"];
|
|
9100
|
+
const knownSwitchers = ["select", "radios", "radios-inline", "modal", "select-inline"];
|
|
8855
9101
|
const switcherType = knownSwitchers.includes(config.switcher) ? config.switcher : "select";
|
|
8856
9102
|
let switcher;
|
|
8857
9103
|
if (switcherType === "select") {
|
|
@@ -8887,6 +9133,14 @@ class Theme {
|
|
|
8887
9133
|
readOnly: config.readOnly
|
|
8888
9134
|
});
|
|
8889
9135
|
}
|
|
9136
|
+
if (switcherType === "select-inline") {
|
|
9137
|
+
switcher = this.getSwitcherSelectInline({
|
|
9138
|
+
values: config.switcherOptionValues,
|
|
9139
|
+
titles: config.switcherOptionsLabels,
|
|
9140
|
+
id: config.id + "-switcher-" + randomId,
|
|
9141
|
+
readOnly: config.readOnly
|
|
9142
|
+
});
|
|
9143
|
+
}
|
|
8890
9144
|
switcher.container.classList.add("jedi-switcher");
|
|
8891
9145
|
container.appendChild(header);
|
|
8892
9146
|
container.appendChild(body);
|
|
@@ -8952,6 +9206,7 @@ class Theme {
|
|
|
8952
9206
|
content: config.description,
|
|
8953
9207
|
id: descriptionId
|
|
8954
9208
|
});
|
|
9209
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
8955
9210
|
if (((_a = config == null ? void 0 : config.info) == null ? void 0 : _a.variant) === "modal") {
|
|
8956
9211
|
this.infoAsModal(info, config.id, config.info);
|
|
8957
9212
|
}
|
|
@@ -8959,11 +9214,12 @@ class Theme {
|
|
|
8959
9214
|
if (isObject(config.info)) {
|
|
8960
9215
|
container.appendChild(info.container);
|
|
8961
9216
|
}
|
|
9217
|
+
container.appendChild(switcherSlot);
|
|
8962
9218
|
container.appendChild(br);
|
|
8963
9219
|
container.appendChild(description);
|
|
8964
9220
|
container.appendChild(messages);
|
|
8965
9221
|
container.appendChild(actions);
|
|
8966
|
-
return { container, label, info, labelText, description, messages, actions };
|
|
9222
|
+
return { container, label, info, labelText, description, messages, actions, switcherSlot };
|
|
8967
9223
|
}
|
|
8968
9224
|
/**
|
|
8969
9225
|
* A Textarea
|
|
@@ -8990,6 +9246,7 @@ class Theme {
|
|
|
8990
9246
|
const messages = this.getMessagesSlot({
|
|
8991
9247
|
id: messagesId
|
|
8992
9248
|
});
|
|
9249
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
8993
9250
|
input.setAttribute("aria-describedby", describedBy);
|
|
8994
9251
|
input.setAttribute("id", config.id);
|
|
8995
9252
|
input.setAttribute("name", config.id);
|
|
@@ -9001,11 +9258,12 @@ class Theme {
|
|
|
9001
9258
|
if (isObject(config.info)) {
|
|
9002
9259
|
container.appendChild(info.container);
|
|
9003
9260
|
}
|
|
9261
|
+
container.appendChild(switcherSlot);
|
|
9004
9262
|
container.appendChild(input);
|
|
9005
9263
|
container.appendChild(description);
|
|
9006
9264
|
container.appendChild(messages);
|
|
9007
9265
|
container.appendChild(actions);
|
|
9008
|
-
return { container, input, label, info, labelText, description, messages, actions };
|
|
9266
|
+
return { container, input, label, info, labelText, description, messages, actions, switcherSlot };
|
|
9009
9267
|
}
|
|
9010
9268
|
adaptForTableTextareaControl(control) {
|
|
9011
9269
|
this.visuallyHidden(control.label);
|
|
@@ -9037,6 +9295,7 @@ class Theme {
|
|
|
9037
9295
|
const messages = this.getMessagesSlot({
|
|
9038
9296
|
id: messagesId
|
|
9039
9297
|
});
|
|
9298
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
9040
9299
|
input.setAttribute("aria-describedby", describedBy);
|
|
9041
9300
|
input.setAttribute("type", config.type);
|
|
9042
9301
|
input.setAttribute("id", config.id);
|
|
@@ -9049,11 +9308,12 @@ class Theme {
|
|
|
9049
9308
|
if (isObject(config.info)) {
|
|
9050
9309
|
container.appendChild(info.container);
|
|
9051
9310
|
}
|
|
9311
|
+
container.appendChild(switcherSlot);
|
|
9052
9312
|
container.appendChild(input);
|
|
9053
9313
|
container.appendChild(description);
|
|
9054
9314
|
container.appendChild(messages);
|
|
9055
9315
|
container.appendChild(actions);
|
|
9056
|
-
return { container, input, label, info, labelText, description, messages, actions };
|
|
9316
|
+
return { container, input, label, info, labelText, description, messages, actions, switcherSlot };
|
|
9057
9317
|
}
|
|
9058
9318
|
getInputRangeControl(config) {
|
|
9059
9319
|
const control = this.getInputControl(config);
|
|
@@ -9123,8 +9383,10 @@ class Theme {
|
|
|
9123
9383
|
radios.push(radio);
|
|
9124
9384
|
labels.push(label);
|
|
9125
9385
|
});
|
|
9386
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
9126
9387
|
container.appendChild(fieldset);
|
|
9127
9388
|
fieldset.appendChild(legend);
|
|
9389
|
+
legend.appendChild(switcherSlot);
|
|
9128
9390
|
if (isObject(config.info)) {
|
|
9129
9391
|
legendText.after(info.container);
|
|
9130
9392
|
}
|
|
@@ -9147,7 +9409,8 @@ class Theme {
|
|
|
9147
9409
|
labelTexts,
|
|
9148
9410
|
radioControls,
|
|
9149
9411
|
description,
|
|
9150
|
-
messages
|
|
9412
|
+
messages,
|
|
9413
|
+
switcherSlot
|
|
9151
9414
|
};
|
|
9152
9415
|
}
|
|
9153
9416
|
adaptForTableRadiosControl(control) {
|
|
@@ -9184,6 +9447,7 @@ class Theme {
|
|
|
9184
9447
|
input.setAttribute("id", config.id);
|
|
9185
9448
|
input.setAttribute("name", config.id);
|
|
9186
9449
|
input.setAttribute("aria-describedby", describedBy);
|
|
9450
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
9187
9451
|
if (((_a = config == null ? void 0 : config.info) == null ? void 0 : _a.variant) === "modal") {
|
|
9188
9452
|
this.infoAsModal(info, config.id, config.info);
|
|
9189
9453
|
}
|
|
@@ -9194,9 +9458,10 @@ class Theme {
|
|
|
9194
9458
|
if (isObject(config.info)) {
|
|
9195
9459
|
formGroup.appendChild(info.container);
|
|
9196
9460
|
}
|
|
9461
|
+
formGroup.appendChild(switcherSlot);
|
|
9197
9462
|
formGroup.appendChild(description);
|
|
9198
9463
|
formGroup.appendChild(messages);
|
|
9199
|
-
return { container, formGroup, input, label, info, labelText, description, messages, actions };
|
|
9464
|
+
return { container, formGroup, input, label, info, labelText, description, messages, actions, switcherSlot };
|
|
9200
9465
|
}
|
|
9201
9466
|
adaptForTableCheckboxControl(control, td) {
|
|
9202
9467
|
this.visuallyHidden(control.label);
|
|
@@ -9253,8 +9518,10 @@ class Theme {
|
|
|
9253
9518
|
if (((_a = config == null ? void 0 : config.info) == null ? void 0 : _a.variant) === "modal") {
|
|
9254
9519
|
this.infoAsModal(info, config.id, config.info);
|
|
9255
9520
|
}
|
|
9521
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
9256
9522
|
container.appendChild(fieldset);
|
|
9257
9523
|
fieldset.appendChild(legend);
|
|
9524
|
+
legend.appendChild(switcherSlot);
|
|
9258
9525
|
if (isObject(config.info)) {
|
|
9259
9526
|
legendText.after(info.container);
|
|
9260
9527
|
}
|
|
@@ -9276,7 +9543,8 @@ class Theme {
|
|
|
9276
9543
|
labelTexts,
|
|
9277
9544
|
checkboxControls,
|
|
9278
9545
|
description,
|
|
9279
|
-
messages
|
|
9546
|
+
messages,
|
|
9547
|
+
switcherSlot
|
|
9280
9548
|
};
|
|
9281
9549
|
}
|
|
9282
9550
|
adaptForTableCheckboxesControl(control, td) {
|
|
@@ -9319,6 +9587,7 @@ class Theme {
|
|
|
9319
9587
|
}
|
|
9320
9588
|
input.appendChild(option);
|
|
9321
9589
|
});
|
|
9590
|
+
const switcherSlot = this.getSwitcherSlot();
|
|
9322
9591
|
if (((_a = config == null ? void 0 : config.info) == null ? void 0 : _a.variant) === "modal") {
|
|
9323
9592
|
this.infoAsModal(info, config.id, config.info);
|
|
9324
9593
|
}
|
|
@@ -9326,11 +9595,12 @@ class Theme {
|
|
|
9326
9595
|
if (isObject(config.info)) {
|
|
9327
9596
|
container.appendChild(info.container);
|
|
9328
9597
|
}
|
|
9598
|
+
container.appendChild(switcherSlot);
|
|
9329
9599
|
container.appendChild(input);
|
|
9330
9600
|
container.appendChild(description);
|
|
9331
9601
|
container.appendChild(messages);
|
|
9332
9602
|
container.appendChild(actions);
|
|
9333
|
-
return { container, input, label, info, labelText, description, messages, actions };
|
|
9603
|
+
return { container, input, label, info, labelText, description, messages, actions, switcherSlot };
|
|
9334
9604
|
}
|
|
9335
9605
|
adaptForTableSelectControl(control) {
|
|
9336
9606
|
this.visuallyHidden(control.label);
|
|
@@ -9404,6 +9674,31 @@ class Theme {
|
|
|
9404
9674
|
setSwitcherOptionActive(btn, active) {
|
|
9405
9675
|
btn.classList.toggle("jedi-switcher-option-active", active);
|
|
9406
9676
|
}
|
|
9677
|
+
/**
|
|
9678
|
+
* Compact inline <select> to switch between multiple editors options (no dialog)
|
|
9679
|
+
*/
|
|
9680
|
+
getSwitcherSelectInline(config) {
|
|
9681
|
+
const container = document.createElement("span");
|
|
9682
|
+
const input = document.createElement("select");
|
|
9683
|
+
container.classList.add("jedi-switcher-select-inline");
|
|
9684
|
+
container.style.display = "inline-block";
|
|
9685
|
+
input.classList.add("jedi-switcher-select-inline-input");
|
|
9686
|
+
input.style.width = "auto";
|
|
9687
|
+
input.setAttribute("aria-label", "Switch type");
|
|
9688
|
+
if (config.readOnly) {
|
|
9689
|
+
input.setAttribute("disabled", "");
|
|
9690
|
+
}
|
|
9691
|
+
config.values.forEach((value, index2) => {
|
|
9692
|
+
const option = document.createElement("option");
|
|
9693
|
+
option.setAttribute("value", value);
|
|
9694
|
+
if (config.titles && config.titles[index2]) {
|
|
9695
|
+
option.textContent = config.titles[index2];
|
|
9696
|
+
}
|
|
9697
|
+
input.appendChild(option);
|
|
9698
|
+
});
|
|
9699
|
+
container.appendChild(input);
|
|
9700
|
+
return { container, input };
|
|
9701
|
+
}
|
|
9407
9702
|
/**
|
|
9408
9703
|
* Another type of error message container used for more complex editors like
|
|
9409
9704
|
* object, array and multiple editors
|
|
@@ -9738,8 +10033,11 @@ class ThemeBootstrap3 extends Theme {
|
|
|
9738
10033
|
chevron.style.display = "inline-block";
|
|
9739
10034
|
chevron.style.transition = "transform 0.1s ease";
|
|
9740
10035
|
chevron.style.marginRight = "0.5em";
|
|
10036
|
+
const titleSpan = document.createElement("span");
|
|
10037
|
+
titleSpan.style.marginRight = "0.5em";
|
|
10038
|
+
titleSpan.textContent = config.title;
|
|
9741
10039
|
toggle.appendChild(chevron);
|
|
9742
|
-
toggle.appendChild(
|
|
10040
|
+
toggle.appendChild(titleSpan);
|
|
9743
10041
|
const collapse = document.createElement("div");
|
|
9744
10042
|
collapse.id = collapseId;
|
|
9745
10043
|
collapse.classList.add("panel-collapse", "collapse");
|
|
@@ -9966,6 +10264,12 @@ class ThemeBootstrap3 extends Theme {
|
|
|
9966
10264
|
control.input.classList.add("input-sm");
|
|
9967
10265
|
return control;
|
|
9968
10266
|
}
|
|
10267
|
+
getSwitcherSelectInline(config) {
|
|
10268
|
+
const control = super.getSwitcherSelectInline(config);
|
|
10269
|
+
control.container.style.marginBottom = "5px";
|
|
10270
|
+
control.input.classList.add("input-sm");
|
|
10271
|
+
return control;
|
|
10272
|
+
}
|
|
9969
10273
|
getSwitcherModal(config) {
|
|
9970
10274
|
const control = super.getSwitcherModal(config);
|
|
9971
10275
|
control.trigger.classList.add("label", "label-primary");
|
|
@@ -10260,8 +10564,11 @@ class ThemeBootstrap4 extends Theme {
|
|
|
10260
10564
|
}
|
|
10261
10565
|
chevron.classList.add("d-inline-block", "mr-2");
|
|
10262
10566
|
chevron.style.transition = "transform 0.1s ease";
|
|
10567
|
+
const titleSpan = document.createElement("span");
|
|
10568
|
+
titleSpan.classList.add("mr-1");
|
|
10569
|
+
titleSpan.textContent = config.title;
|
|
10263
10570
|
toggle.appendChild(chevron);
|
|
10264
|
-
toggle.appendChild(
|
|
10571
|
+
toggle.appendChild(titleSpan);
|
|
10265
10572
|
const collapse = document.createElement("div");
|
|
10266
10573
|
collapse.id = collapseId;
|
|
10267
10574
|
collapse.classList.add("collapse");
|
|
@@ -10499,6 +10806,12 @@ class ThemeBootstrap4 extends Theme {
|
|
|
10499
10806
|
control.input.classList.add("form-control-sm");
|
|
10500
10807
|
return control;
|
|
10501
10808
|
}
|
|
10809
|
+
getSwitcherSelectInline(config) {
|
|
10810
|
+
const control = super.getSwitcherSelectInline(config);
|
|
10811
|
+
control.container.classList.add("mb-2");
|
|
10812
|
+
control.input.classList.add("form-control", "form-control-sm");
|
|
10813
|
+
return control;
|
|
10814
|
+
}
|
|
10502
10815
|
getSwitcherModal(config) {
|
|
10503
10816
|
const control = super.getSwitcherModal(config);
|
|
10504
10817
|
control.trigger.classList.add("badge", "badge-primary");
|
|
@@ -10805,8 +11118,11 @@ class ThemeBootstrap5 extends Theme {
|
|
|
10805
11118
|
}
|
|
10806
11119
|
chevron.classList.add("d-inline-block", "me-2");
|
|
10807
11120
|
chevron.style.transition = "transform 0.1s ease";
|
|
11121
|
+
const titleSpan = document.createElement("span");
|
|
11122
|
+
titleSpan.classList.add("me-1");
|
|
11123
|
+
titleSpan.textContent = config.title;
|
|
10808
11124
|
toggle.appendChild(chevron);
|
|
10809
|
-
toggle.appendChild(
|
|
11125
|
+
toggle.appendChild(titleSpan);
|
|
10810
11126
|
const collapse = document.createElement("div");
|
|
10811
11127
|
collapse.id = collapseId;
|
|
10812
11128
|
collapse.classList.add("accordion-collapse", "collapse");
|
|
@@ -11044,6 +11360,12 @@ class ThemeBootstrap5 extends Theme {
|
|
|
11044
11360
|
control.input.classList.add("form-select-sm");
|
|
11045
11361
|
return control;
|
|
11046
11362
|
}
|
|
11363
|
+
getSwitcherSelectInline(config) {
|
|
11364
|
+
const control = super.getSwitcherSelectInline(config);
|
|
11365
|
+
control.container.classList.add("mb-1");
|
|
11366
|
+
control.input.classList.add("form-select", "form-select-sm");
|
|
11367
|
+
return control;
|
|
11368
|
+
}
|
|
11047
11369
|
getSwitcherModal(config) {
|
|
11048
11370
|
const control = super.getSwitcherModal(config);
|
|
11049
11371
|
control.trigger.classList.add("badge", "bg-primary");
|