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.
@@ -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
- off(name) {
1782
- this.listeners.delete(name);
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 card = getSchemaXOption(this.instance.schema, "card") ?? this.instance.jedison.getOption("card");
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 = getSchemaXOption(this.instance.schema, "embedSwitcher") ?? this.instance.jedison.getOption("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
- if (this.embedSwitcher) {
5665
- const slot = this.instance.activeInstance.ui.control.switcherSlot;
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
- slot.innerHTML = "";
5668
- slot.appendChild(this.control.switcher.container);
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.control.checkboxes = [];
6304
- this.control.labels = [];
6305
- this.control.checkboxControls = [];
6306
- this.control.labelTexts = [];
6307
- values.forEach((value, index2) => {
6308
- const checkboxId = id + "-" + index2;
6309
- const checkboxControl = document.createElement("div");
6310
- const checkbox = document.createElement("input");
6311
- const label = document.createElement("label");
6312
- const labelText = document.createElement("span");
6313
- checkbox.setAttribute("type", "checkbox");
6314
- checkbox.setAttribute("id", checkboxId);
6315
- checkbox.setAttribute("name", id);
6316
- checkbox.setAttribute("value", value);
6317
- checkbox.setAttribute("aria-describedby", describedBy);
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 = document.createElement("div");
8448
- switcherSlot.classList.add("jedi-switcher-slot");
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 = document.createElement("div");
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(document.createTextNode(config.title));
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 = document.createElement("div");
8768
- switcherSlot.classList.add("jedi-switcher-slot");
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(document.createTextNode(config.title));
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(document.createTextNode(config.title));
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(document.createTextNode(config.title));
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");