@ixfx/components 0.5.2 → 0.5.3

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.
Files changed (39) hide show
  1. package/bundle/index.d.ts +87 -1
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +326 -23
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.d.ts +1 -1
  6. package/dist/button.d.ts +1 -1
  7. package/dist/button.d.ts.map +1 -1
  8. package/dist/colour-picker.d.ts +1 -1
  9. package/dist/crumbs.d.ts +1 -1
  10. package/dist/{icon-DpA9x2Ve.d.ts → icon-BUwP1CZ1.d.ts} +2 -2
  11. package/dist/icon-BUwP1CZ1.d.ts.map +1 -0
  12. package/dist/icons.d.ts +2 -2
  13. package/dist/{index-DfEkTGvT.d.ts → index-B1UKcA7l.d.ts} +3 -3
  14. package/dist/{index-DfEkTGvT.d.ts.map → index-B1UKcA7l.d.ts.map} +1 -1
  15. package/dist/{index-D_ftz_IT.d.ts → index-BKAlRgbq.d.ts} +2 -2
  16. package/dist/{index-D_ftz_IT.d.ts.map → index-BKAlRgbq.d.ts.map} +1 -1
  17. package/dist/{index-CoqtMSd9.d.ts → index-BUB5SICW.d.ts} +2 -2
  18. package/dist/{index-CoqtMSd9.d.ts.map → index-BUB5SICW.d.ts.map} +1 -1
  19. package/dist/{index-BtGFYfaK.d.ts → index-RqMh1i-O.d.ts} +2 -2
  20. package/dist/{index-BtGFYfaK.d.ts.map → index-RqMh1i-O.d.ts.map} +1 -1
  21. package/dist/index.d.ts +95 -9
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +304 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/{labelled-input-base-DiTme1JO.d.ts → labelled-input-base-Dp_9KP0G.d.ts} +2 -2
  26. package/dist/{labelled-input-base-DiTme1JO.d.ts.map → labelled-input-base-Dp_9KP0G.d.ts.map} +1 -1
  27. package/dist/labelled-radial-input.d.ts +2 -2
  28. package/dist/labelled-radial-input.d.ts.map +1 -1
  29. package/dist/labelled-range-input.d.ts +1 -1
  30. package/dist/{menu-item-DSyf9f_L.d.ts → menu-item-CQ4Qg731.d.ts} +2 -2
  31. package/dist/{menu-item-DSyf9f_L.d.ts.map → menu-item-CQ4Qg731.d.ts.map} +1 -1
  32. package/dist/menu.d.ts +2 -2
  33. package/dist/panel.d.ts +1 -1
  34. package/dist/{tab-list-BohmbvqF.d.ts → tab-list-VtWT-_FG.d.ts} +2 -2
  35. package/dist/{tab-list-BohmbvqF.d.ts.map → tab-list-VtWT-_FG.d.ts.map} +1 -1
  36. package/dist/tabs.d.ts +1 -1
  37. package/docs-user/tabs.md +95 -1
  38. package/package.json +1 -1
  39. package/dist/icon-DpA9x2Ve.d.ts.map +0 -1
package/bundle/index.js CHANGED
@@ -23925,6 +23925,331 @@ __decorate([property({ attribute: false })], TabListItemElement.prototype, "regi
23925
23925
  __decorate([state()], TabListItemElement.prototype, "_compact", void 0);
23926
23926
  TabListItemElement = __decorate([safeCustomElement(`ixfx-tab-list-item`)], TabListItemElement);
23927
23927
  //#endregion
23928
+ //#region src/tabs/tab-panel.ts
23929
+ let TabPanelElement = class TabPanelElement extends i {
23930
+ render() {
23931
+ return b`<slot></slot>`;
23932
+ }
23933
+ static {
23934
+ this.styles = [themeFallbacks, i$3`
23935
+ :host {
23936
+ display:none;
23937
+ height:100%;
23938
+ width:100%;
23939
+ }
23940
+
23941
+ :host([selected]) {
23942
+ background: var(--surface-3);
23943
+ display:block;
23944
+ }
23945
+ `];
23946
+ }
23947
+ };
23948
+ TabPanelElement = __decorate([safeCustomElement(`ixfx-tab-panel`)], TabPanelElement);
23949
+ //#endregion
23950
+ //#region src/tabs/tab-controller.ts
23951
+ /**
23952
+ * Connects an `ixfx-tab-list` to an `ixfx-tab-panels` container, handling the
23953
+ * wiring between them (header clicks show the matching panel, closing a tab
23954
+ * removes its panel, etc.) and offering an API to select, add, remove, rename
23955
+ * and reorder tabs.
23956
+ *
23957
+ * @example
23958
+ * ```ts
23959
+ * const ctrl = new TabController(
23960
+ * document.querySelector('ixfx-tab-list'),
23961
+ * document.querySelector('ixfx-tab-panels'),
23962
+ * );
23963
+ * ctrl.connect();
23964
+ *
23965
+ * ctrl.addTab({ label: 'Console', content: 'Console panel' });
23966
+ * ctrl.selectTab('Console');
23967
+ * ```
23968
+ */
23969
+ var TabController = class {
23970
+ #list;
23971
+ #panels;
23972
+ #opts;
23973
+ #tabs = [];
23974
+ #signal;
23975
+ #observer;
23976
+ #commands;
23977
+ #registeredCommands = /* @__PURE__ */ new Set();
23978
+ constructor(list, panels, options = {}) {
23979
+ this.#list = list;
23980
+ this.#panels = panels;
23981
+ this.#opts = options;
23982
+ this.#commands = options.commands;
23983
+ }
23984
+ connect() {
23985
+ this.disconnect();
23986
+ this.#signal = new AbortController();
23987
+ const { signal } = this.#signal;
23988
+ this.#list.addEventListener(`change`, this.#onChange, { signal });
23989
+ this.#list.addEventListener(`reorder`, this.#onReorder, { signal });
23990
+ this.#list.addEventListener(`close`, this.#onClose, { signal });
23991
+ this.#observer = new MutationObserver(() => this.#rebuild());
23992
+ this.#observer.observe(this.#list, { childList: true });
23993
+ this.#observer.observe(this.#panels, { childList: true });
23994
+ this.#rebuild();
23995
+ this.#panels.syncWithList(this.#list);
23996
+ for (const tab of this.#tabs) this.#registerCommand(tab);
23997
+ }
23998
+ disconnect() {
23999
+ this.#signal?.abort();
24000
+ this.#signal = void 0;
24001
+ this.#observer?.disconnect();
24002
+ this.#observer = void 0;
24003
+ for (const tab of this.#tabs) this.#unregisterCommand(tab);
24004
+ this.#registeredCommands.clear();
24005
+ this.#tabs = [];
24006
+ }
24007
+ /**
24008
+ * Select a tab as if it was clicked — activates the header (deactivating the
24009
+ * others) and shows its panel.
24010
+ *
24011
+ * `sel` may be a tab id, the panel id its `for` points at, its label text
24012
+ * (case-insensitive), or the tab item element itself.
24013
+ *
24014
+ * Returns true if a tab was found.
24015
+ */
24016
+ selectTab(sel) {
24017
+ const tab = this.#resolveTab(sel);
24018
+ if (!tab) return false;
24019
+ const previous = this.getSelected();
24020
+ if (previous?.id === tab.id) {
24021
+ this.#panels.selectPanel(tab.forId);
24022
+ return true;
24023
+ }
24024
+ this.#list.selectElement(tab.item);
24025
+ this.#panels.selectPanel(tab.forId);
24026
+ this.#opts.onSelect?.(tab, previous);
24027
+ return true;
24028
+ }
24029
+ selectNext() {
24030
+ return this.#selectOffset(1);
24031
+ }
24032
+ selectPrevious() {
24033
+ return this.#selectOffset(-1);
24034
+ }
24035
+ getSelected() {
24036
+ return this.#tabs.find((t) => t.item.hasAttribute(`selected`));
24037
+ }
24038
+ getTabs() {
24039
+ return [...this.#tabs];
24040
+ }
24041
+ getTab(id) {
24042
+ return this.#tabs.find((t) => t.id === id);
24043
+ }
24044
+ addTab(opts) {
24045
+ const { id, forId } = this.#idsFor(opts);
24046
+ const item = document.createElement(`ixfx-tab-list-item`);
24047
+ item.id = id;
24048
+ item.setAttribute(`for`, forId);
24049
+ item.closeable = opts.closeable ?? true;
24050
+ item.append(opts.label);
24051
+ if (opts.iconName) item.iconName = opts.iconName;
24052
+ if (opts.description) item.description = opts.description;
24053
+ for (const el of opts.toolbar ?? []) {
24054
+ el.slot = `toolbar`;
24055
+ item.append(el);
24056
+ }
24057
+ const panel = document.createElement(`ixfx-tab-panel`);
24058
+ panel.id = forId;
24059
+ if (opts.content !== void 0) this.#fillContent(panel, opts.content);
24060
+ const index = Math.max(0, Math.min(opts.index ?? this.#tabs.length, this.#tabs.length));
24061
+ this.#insertElement(this.#list, item, index);
24062
+ this.#insertElement(this.#panels, panel, index);
24063
+ const tab = {
24064
+ id,
24065
+ forId,
24066
+ item,
24067
+ panel,
24068
+ label: opts.label,
24069
+ iconName: opts.iconName
24070
+ };
24071
+ this.#tabs.splice(index, 0, tab);
24072
+ this.#registerCommand(tab);
24073
+ this.#opts.onAdd?.(tab);
24074
+ if (opts.select ?? true) this.selectTab(id);
24075
+ return tab;
24076
+ }
24077
+ removeTab(sel) {
24078
+ const tab = this.#resolveTab(sel);
24079
+ if (!tab) return false;
24080
+ const index = this.#tabs.indexOf(tab);
24081
+ const adjacent = tab.item.hasAttribute(`selected`) ? this.#adjacentTab(index) : void 0;
24082
+ tab.item.remove();
24083
+ tab.panel.remove();
24084
+ this.#removeFromIndex(tab);
24085
+ this.#unregisterCommand(tab);
24086
+ this.#opts.onRemove?.(tab);
24087
+ if (adjacent) this.selectTab(adjacent.id);
24088
+ return true;
24089
+ }
24090
+ renameTab(sel, label) {
24091
+ const tab = this.#resolveTab(sel);
24092
+ if (!tab) return false;
24093
+ for (const child of [...tab.item.childNodes]) {
24094
+ if (child.nodeType === Node.ELEMENT_NODE && child.slot === `toolbar`) continue;
24095
+ tab.item.removeChild(child);
24096
+ }
24097
+ tab.item.prepend(label);
24098
+ tab.label = label;
24099
+ this.#reregisterCommand(tab);
24100
+ return true;
24101
+ }
24102
+ setTabIcon(sel, iconName) {
24103
+ const tab = this.#resolveTab(sel);
24104
+ if (!tab) return false;
24105
+ if (iconName) {
24106
+ tab.item.iconName = iconName;
24107
+ tab.iconName = iconName;
24108
+ } else {
24109
+ tab.item.iconName = void 0;
24110
+ tab.item.removeAttribute(`icon-name`);
24111
+ tab.iconName = void 0;
24112
+ }
24113
+ return true;
24114
+ }
24115
+ #onChange = (event) => {
24116
+ const detail = event.detail;
24117
+ this.#panels.selectPanel(detail.for);
24118
+ const tab = this.#tabs.find((t) => t.forId === detail.for);
24119
+ if (!tab) return;
24120
+ const previous = detail.previous ? this.#tabs.find((t) => t.id === detail.previous) : void 0;
24121
+ this.#opts.onSelect?.(tab, previous);
24122
+ };
24123
+ #onReorder = () => {
24124
+ this.#rebuild();
24125
+ this.#opts.onReorder?.(this.#tabs);
24126
+ };
24127
+ #onClose = (event) => {
24128
+ const item = event.target?.closest(`ixfx-tab-list-item`);
24129
+ const tab = item ? this.#tabByItem(item) : void 0;
24130
+ if (!tab) return;
24131
+ const index = this.#tabs.indexOf(tab);
24132
+ const adjacent = tab.item.hasAttribute(`selected`) ? this.#adjacentTab(index) : void 0;
24133
+ tab.panel.remove();
24134
+ this.#removeFromIndex(tab);
24135
+ this.#unregisterCommand(tab);
24136
+ this.#opts.onRemove?.(tab);
24137
+ if (adjacent) this.selectTab(adjacent.id);
24138
+ };
24139
+ #selectOffset(offset) {
24140
+ const tabs = this.#tabs;
24141
+ if (tabs.length === 0) return false;
24142
+ const current = this.getSelected();
24143
+ const next = ((current ? tabs.indexOf(current) : offset === 1 ? -1 : 0) + offset + tabs.length) % tabs.length;
24144
+ return this.selectTab(tabs[next].id);
24145
+ }
24146
+ #resolveTab(sel) {
24147
+ if (typeof sel !== `string`) return this.#tabs.find((t) => t.item === sel);
24148
+ const label = sel.trim().toLowerCase();
24149
+ return this.#tabs.find((t) => t.id === sel) ?? this.#tabs.find((t) => t.forId === sel) ?? this.#tabs.find((t) => t.label.toLowerCase() === label);
24150
+ }
24151
+ #tabByItem(item) {
24152
+ return this.#tabs.find((t) => t.item === item);
24153
+ }
24154
+ #adjacentTab(index) {
24155
+ const tabs = this.#tabs;
24156
+ if (tabs.length <= 1) return void 0;
24157
+ return tabs[index + 1] ?? tabs[index - 1];
24158
+ }
24159
+ #removeFromIndex(tab) {
24160
+ const index = this.#tabs.indexOf(tab);
24161
+ if (index >= 0) this.#tabs.splice(index, 1);
24162
+ }
24163
+ #idsFor(opts) {
24164
+ const base = this.#slug(opts.label) || `tab`;
24165
+ return {
24166
+ id: opts.id ?? this.#uniqueId(`tab-${base}`),
24167
+ forId: opts.forId ?? this.#uniqueId(`panel-${base}`)
24168
+ };
24169
+ }
24170
+ #slug(value) {
24171
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, `-`).replace(/^-+|-+$/g, ``);
24172
+ }
24173
+ #uniqueId(base) {
24174
+ let candidate = base;
24175
+ let n = 2;
24176
+ while (document.getElementById(candidate)) candidate = `${base}-${n++}`;
24177
+ return candidate;
24178
+ }
24179
+ #fillContent(panel, content) {
24180
+ if (typeof content === `function`) {
24181
+ content(panel);
24182
+ return;
24183
+ }
24184
+ if (typeof content === `string`) {
24185
+ panel.append(document.createTextNode(content));
24186
+ return;
24187
+ }
24188
+ panel.append(content);
24189
+ }
24190
+ #insertElement(container, el, index) {
24191
+ const children = Array.from(container.children);
24192
+ container.insertBefore(el, children[index] ?? null);
24193
+ }
24194
+ #rebuild() {
24195
+ const panels = /* @__PURE__ */ new Map();
24196
+ for (const el of this.#panels.querySelectorAll(`ixfx-tab-panel`)) panels.set(el.id, el);
24197
+ const tabs = [];
24198
+ for (const item of this.#list.querySelectorAll(`ixfx-tab-list-item`)) {
24199
+ const forId = item.getAttribute(`for`) ?? ``;
24200
+ const panel = panels.get(forId);
24201
+ if (!panel) continue;
24202
+ tabs.push({
24203
+ id: item.id || forId,
24204
+ forId,
24205
+ item,
24206
+ panel,
24207
+ label: this.#labelOf(item),
24208
+ iconName: item.iconName
24209
+ });
24210
+ }
24211
+ this.#tabs = tabs;
24212
+ }
24213
+ /** The tab's visible label text, excluding any `slot="toolbar"` content. */
24214
+ #labelOf(item) {
24215
+ const clone = item.cloneNode(true);
24216
+ clone.querySelectorAll(`[slot="toolbar"]`).forEach((el) => el.remove());
24217
+ return (clone.textContent ?? ``).trim();
24218
+ }
24219
+ #registerCommand(tab) {
24220
+ if (!this.#commands) return;
24221
+ if (tab.item.commandActive) return;
24222
+ if (this.#commands.has(tab.id)) return;
24223
+ this.#commands.register({
24224
+ id: tab.id,
24225
+ label: tab.label,
24226
+ description: tab.item.description ?? tab.label,
24227
+ icon: tab.iconName,
24228
+ execute: () => {
24229
+ this.selectTab(tab.id);
24230
+ }
24231
+ });
24232
+ this.#registeredCommands.add(tab.id);
24233
+ }
24234
+ #unregisterCommand(tab) {
24235
+ if (!this.#commands) return;
24236
+ if (this.#registeredCommands.has(tab.id)) {
24237
+ this.#commands.unregister(tab.id);
24238
+ this.#registeredCommands.delete(tab.id);
24239
+ }
24240
+ }
24241
+ #reregisterCommand(tab) {
24242
+ if (!this.#commands || !this.#registeredCommands.has(tab.id)) return;
24243
+ const existing = this.#commands.get(tab.id);
24244
+ if (!existing) return;
24245
+ this.#commands.unregister(tab.id);
24246
+ this.#commands.register({
24247
+ ...existing,
24248
+ label: tab.label
24249
+ });
24250
+ }
24251
+ };
24252
+ //#endregion
23928
24253
  //#region src/util/drag-ghost.ts
23929
24254
  /**
23930
24255
  * Theme-aware floating element helper.
@@ -24515,28 +24840,6 @@ __decorate([property({
24515
24840
  })], TabListElement.prototype, "dragMode", void 0);
24516
24841
  TabListElement = __decorate([safeCustomElement(`ixfx-tab-list`)], TabListElement);
24517
24842
  //#endregion
24518
- //#region src/tabs/tab-panel.ts
24519
- let TabPanelElement = class TabPanelElement extends i {
24520
- render() {
24521
- return b`<slot></slot>`;
24522
- }
24523
- static {
24524
- this.styles = [themeFallbacks, i$3`
24525
- :host {
24526
- display:none;
24527
- height:100%;
24528
- width:100%;
24529
- }
24530
-
24531
- :host([selected]) {
24532
- background: var(--surface-3);
24533
- display:block;
24534
- }
24535
- `];
24536
- }
24537
- };
24538
- TabPanelElement = __decorate([safeCustomElement(`ixfx-tab-panel`)], TabPanelElement);
24539
- //#endregion
24540
24843
  //#region src/tabs/tab-panels.ts
24541
24844
  let TabPanelsElement = class TabPanelsElement extends i {
24542
24845
  /**
@@ -27238,6 +27541,6 @@ function init() {
27238
27541
  console.log(`Init`);
27239
27542
  }
27240
27543
  //#endregion
27241
- export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, SelectHorizontalElement, SliderInputElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, collectDataResult, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, createPillRenderer, createTreeListAdapter, createVerticalListAdapter, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
27544
+ export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataController, DataDisplayComponent, EditableLabel, EditableNumber, FormElement, FormGroupElement, FormPartElement, GroupedItemListerElement, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, NotificationManager, NotificationPillElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotHistogram, PlotMultiAxis, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, SelectHorizontalElement, SliderInputElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabController, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, collectDataResult, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, createPillRenderer, createTreeListAdapter, createVerticalListAdapter, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
27242
27545
 
27243
27546
  //# sourceMappingURL=index.js.map