@kitlangton/knobs 0.4.0-next.13 → 0.4.0-next.15

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/README.md CHANGED
@@ -384,7 +384,7 @@ Panels and switchers are keyboard-first:
384
384
  | Arrows on a pad or curve handle | Move the puck or handle (`⇧` ×10, `⌥` finest); `j` / `k` or `Tab` move on |
385
385
  | On a gradient strip or curve graph | Arrows move the selected stop or point; `Tab` / `⇧Tab` and `[` / `]` pick another; `n` adds one, `Delete` removes it; `Enter` edits a stop's colour (`Esc` returns) |
386
386
  | `[` / `]` | Cycle presets and saved variants from anywhere in the panel; with no preset strip, cycle tabs |
387
- | `1`–`9` | Pick the focused row's Nth option: a choice (segmented or menu) or a curve's, easing's or gradient's presets. Anywhere else in the panel, pick the preset strip's Nth chip (a design's variants). While you use keys, tiny digit hints show on the options once focus settles, and on the strip's chips while focus is on the strip or the panel. A number row keeps its digits for inline edits, and a page's card for its group presets |
387
+ | `1`–`9` | Pick the focused row's Nth option: a choice (segmented or menu) or a curve's, easing's or gradient's presets. Anywhere else in the panel, pick the preset strip's Nth chip (a design's variants). While you use keys, tiny digit hints show on the options once focus settles, and on the strip's chips while focus is on the strip or the panel (`hints: { digits: "always" }` on the mount keeps them on the chips all the time, small and dim before each name). A number row keeps its digits for inline edits, and a page's card for its group presets |
388
388
  | `⌥1`–`⌥9` | Show tab 1–9 |
389
389
  | `/` | Focus the search field (`Esc` clears it, then hands focus back; `↓` or `Enter` go to the first row left) |
390
390
  | `Home` / `End` | Jump slider to `min` or `max` |
@@ -835,6 +835,16 @@ panel.tab("emitter") // shows a tab; panel.tab() answers the one showing
835
835
  A pinned `variants: true` choice is an ordinary choice with a row: pinned wins, and its options
836
836
  make no presets. A tab whose rows no preset moves shows no preset strip; a variants choice moves
837
837
  its own tab (or every tab, if it has none).
838
+ - **Keys presets leave alone, in place.** `inPresets: false` on a field, or `inPresets: { Motion:
839
+ false }` on the store for a whole group, keeps presets, scoped presets and saved variants off
840
+ those keys exactly as they stay off pinned ones (and a preset's chip stays lit when they move),
841
+ but the rows stay where they are. A pinned key is one of these, moved to the top. The rule, for
842
+ `inPresets: false` and `pinned` groups alike: presets and variants from *other* scopes (the
843
+ panel-wide presets, tab scopes, other groups') leave the group alone, but a scope keyed by the
844
+ group's own name still moves it. So `inPresets: { Motion: false }` with
845
+ `scopedPresets: { Motion: { Snappy } }` gives Motion its own strip that state presets never
846
+ touch; its chips apply, save, match and mark only Motion. A field's own `inPresets: false` stays
847
+ out of every scope. `controls.inPresets(key)` says whether presets from other scopes move a key.
838
848
  - **Presets of a tab's own.** `scopedPresets` gives a tab (or a group) presets that belong to it:
839
849
  `{ Sidebars: { snappy, smooth, calm } }`. Its strip shows only on that tab, and a tab without any
840
850
  shows none. A scoped preset moves only its tab's (or group's) keys, never pinned ones or another
@@ -844,9 +854,13 @@ panel.tab("emitter") // shows a tab; panel.tab() answers the one showing
844
854
  A `variants: true` choice on a tab adds its options to that tab's presets. Keys belong to their
845
855
  tab's scope first, then their group's. Plain `presets` then cover only the keys no scope holds;
846
856
  leave them out and only the scoped strips show. One strip shows per tab: the tab's own, else the
847
- first group scope on it. In code, `controls.preset(id, { scope })`, `activePreset(scope)` and
857
+ first group scope on it. In a panel, any other group's presets show at the top of its own card,
858
+ in the strip's look without its tray, so a story's states can lead the panel while its Motion
859
+ group keeps Shipped, Snappy and Calm beside its knobs. Every strip's default chip reads `defaultLabel`; by scope,
860
+ `defaultLabel: { "": "Empty", Motion: "Shipped" }` names each on its own. In code, `controls.preset(id, { scope })`, `activePreset(scope)` and
848
861
  `matchingPreset(scope)` take the tab or group, and `controls.scopeOf(key)` says whose presets
849
- move a key (`""` for plain `presets`, undefined when pinned). An active preset saved while the
862
+ move a key (`""` for plain `presets`, the group's id for a pinned or `inPresets: false`
863
+ group with a scope of its own, else undefined when pinned). An active preset saved while the
850
864
  presets were panel-wide comes back on the scope that now has one by that id, and variants saved
851
865
  then start out in each scope they move.
852
866
 
@@ -1206,7 +1220,7 @@ Scrolling pane bodies, trees and the command palette's list fade their content o
1206
1220
  | Key | Action |
1207
1221
  | --- | --- |
1208
1222
  | `↑` / `↓`, `Home` / `End` | Move; type letters to jump to a label (see `typeahead`) |
1209
- | `←` / `→` | Close or go up / open or go down |
1223
+ | `←` / `→` | Close or go up / open or go down (swapped when the tree is `dir="rtl"`) |
1210
1224
  | `⇧` click or `⇧↑↓`, `⌘` click, `⌘A` | Extend, toggle, select all |
1211
1225
  | `Space` | Select the active row (`⌘Space` toggles it) |
1212
1226
  | `Enter` / `F2` | Rename in place (with `onRename`); otherwise `Enter` calls `onActivate` |
@@ -1259,7 +1273,7 @@ toast("Deleted Barrier", { action: { label: "Undo", run: undo } })
1259
1273
 
1260
1274
  - **`popover(anchor, content, options?)`** places `content` beside an element, a rect or a point. `placement` is `top`, `bottom`, `left` or `right`, each with `-start` or `-end`; it flips when its side is short and the other has more room, then shifts to stay 8px inside the view, and follows its anchor through scrolls and resizes. It grows from the anchor's edge. It takes focus (`focus: "first" | "layer" | "none"`) and gives it back when it closes; Esc, a click outside or focus leaving closes it (`closeOnOutside: false` keeps it), and `trap: true` keeps Tab inside. The handle has `element`, `open`, `reposition()` and `close()` (a promise that resolves once it's gone).
1261
1275
  - **`tooltip(el, content, options?)`** shows after a 500ms pause over the element, or on keyboard focus (not a click's). While one is up, or just after, moving to a neighbour shows its tip at once, with no entrance. A press hides it until the pointer leaves; Esc hides it. `shortcut` shows as key chips (`⌘K` on Apple platforms, `Ctrl+K` elsewhere) and sets `aria-keyshortcuts`; the target gets `aria-describedby` while it shows. Content can be a function, read each time it shows. Split panes use these for their buttons and rails.
1262
- - **`commandPalette({ commands, onRun?, hotkey?, recents?, placeholder? })`** opens on `⌘K` (`hotkey`, `"Mod+K"` by default; `false` for none). With no query it shows recent commands (remembered in localStorage under `recents`; `false` for none), then each `section`. Typing ranks commands by a fuzzy match: letters in order, best at the start, at word starts and in runs. The matched letters light up in the accent while the rest of the label dims, and letters strewn thinly across words don't count. A command answers to its `keywords` and section too. `↑`/`↓` move a highlight that glides (`PgUp`/`PgDn`, `⌘↑`/`⌘↓`), disabled commands are passed over, `Enter` runs, `Esc` or a click outside closes. A `run` that returns a string (or a promise of one) shows it as a toast; a throw shows as an error toast. The handle has `open(query?)`, `close()`, `toggle()`, `isOpen` and `dispose()`.
1276
+ - **`commandPalette({ commands, onRun?, hotkey?, recents?, placeholder?, presence? })`** opens on `⌘K` (`hotkey`, `"Mod+K"` by default; `false` for none). A key summons it, so it fades in and out in about 80ms (`presence: "fade"`); `presence: "none"` (or `false`) shows and hides it at once, and `{ duration?, scale?, blur?, dy? }` gives it the full entrance (from .96, 8px blur and 8px above, over .34s), with any of those changed. With no query it shows recent commands (remembered in localStorage under `recents`; `false` for none), then each `section`. Typing ranks commands by a fuzzy match: letters in order, best at the start, at word starts and in runs. The matched letters light up in the accent while the rest of the label dims, and letters strewn thinly across words don't count. A command answers to its `keywords` and section too. `↑`/`↓` move a highlight that glides (`PgUp`/`PgDn`, `⌘↑`/`⌘↓`), disabled commands are passed over, `Enter` runs, `Esc` or a click outside closes. A `run` that returns a string (or a promise of one) shows it as a toast; a throw shows as an error toast. The handle has `open(query?)`, `close()`, `toggle()`, `isOpen` and `dispose()`.
1263
1277
  - **`commandsFrom(controls, { title?, fields?, reveal? })`** lists a store as commands: its actions and toolbar buttons (with their shortcuts), presets and group presets (the current one marked), toggles ("Turn on …"), one command per choice option, "Reset …" for modified fields, and, with `reveal(key)`, every other field (its current value as the hint) to go to.
1264
1278
  - **`confirm({ title, body?, confirm?, cancel?, destructive? })`** returns `Promise<boolean>`. It's modal over a scrim, keeps Tab inside, and Esc or a click outside cancels. `destructive` puts the button in `--k-critical` and focus on Cancel; otherwise focus starts on the confirming button.
1265
1279
  - **`toast(message, { tone?, linger?, action?, within? })`** shows a pill at the bottom centre for 3.2s (6s for `tone: "error"`). A new message replaces the one showing, and hovering keeps it. Pages show their status (Copied, errors) this way.
@@ -2078,7 +2092,7 @@ The package has two core exports selected through the standard `development` con
2078
2092
  | `readout(field, { preset?, theme?, label? })` | A readout on its own: `{ element, push(value), value, dispose() }`. |
2079
2093
  | `popover(anchor, content, { placement?, offset?, role?, label?, focus?, trap?, closeOnOutside?, onClose? })` | A floating layer that flips and shifts; `{ element, open, reposition(), close() }`. |
2080
2094
  | `tooltip(el, text \| { text, shortcut?, placement?, delay? })` / `tooltips(doc)` | Delayed tooltips with instant hand-off and shortcut chips; `data-tip` attributes. |
2081
- | `commandPalette({ commands, onRun?, hotkey?, recents?, placeholder? })` / `commandsFrom(controls, options?)` | `⌘K` fuzzy command search; a store's actions, presets and fields as commands. |
2095
+ | `commandPalette({ commands, onRun?, hotkey?, recents?, placeholder?, presence? })` / `commandsFrom(controls, options?)` | `⌘K` fuzzy command search; a store's actions, presets and fields as commands. |
2082
2096
  | `confirm({ title, body?, confirm?, cancel?, destructive? })` | `Promise<boolean>`, modal, focus kept inside. |
2083
2097
  | `toast(message, { tone?, linger?, action?, within? })` | A status pill at the bottom centre. |
2084
2098
  | `menu(anchor, items, { placement?, label?, onSelect?, onClose? })` / `contextMenu(target, items, options?)` | Menus with icons, shortcut chips, checks, radios and submenus; a right-click or menu-key menu. |
@@ -46,7 +46,7 @@ import {
46
46
  pushReadout,
47
47
  READOUT,
48
48
  storageKey
49
- } from "./chunk-7kns3qe6.js";
49
+ } from "./chunk-v2g91mrm.js";
50
50
  import {
51
51
  resolveLook,
52
52
  themeOf,
@@ -119,7 +119,7 @@ import {
119
119
  createHintController,
120
120
  pageHints,
121
121
  toggleLayer
122
- } from "./chunk-pdf3zy95.js";
122
+ } from "./chunk-bejz4qcg.js";
123
123
 
124
124
  // src/panel/die.ts
125
125
  var ROUND = 16 * Math.sqrt(5), DIE = { half: 64 + ROUND, round: ROUND, pip: 12 }, PIPS = {
@@ -1029,7 +1029,7 @@ function createPresetStrip(doc, controls, showVariants, run, onAfterChange, pres
1029
1029
  saveButton.type = "button", saveButton.tabIndex = -1, saveButton.setAttribute("aria-label", "Save as variant"), saveButton.setAttribute("aria-keyshortcuts", "Shift+S"), saveButton.dataset.hint = "Save", saveButton.onclick = () => run(save);
1030
1030
  if (track.append(pill), root.append(track), saveButton)
1031
1031
  root.append(saveButton);
1032
- let pillEdges = new Edges, pillY = new Spring(0, 28, 0.86), pillAlpha = new Spring(1, 26, 0.9), entries = [], buttons = [], signature = "", lastVariantsRef = null, lastAppliedId = null, activeState = { activeId: "p:default", activeIndex: 0, isCustom: !1 }, prevActiveId = "", prevActiveIndex = -2, prevIsCustom = !1, prevDrifted = !1, initializedPill = !1, slideUntil = 0, display = "auto", chipMin = 0, scope = null, at = () => scope ?? "", source = () => scope === null ? void 0 : scope === "" ? { presets: controls.presets, variants: controls.variants } : controls.scopes[scope], unpinned = (values) => {
1032
+ let pillEdges = new Edges, pillY = new Spring(0, 28, 0.86), pillAlpha = new Spring(1, 26, 0.9), entries = [], buttons = [], signature = "", lastVariantsRef = null, lastAppliedId = null, activeState = { activeId: "p:default", activeIndex: 0, isCustom: !1 }, prevActiveId = "", prevActiveIndex = -2, prevIsCustom = !1, prevDrifted = !1, initializedPill = !1, slideUntil = 0, display = "auto", digits = !1, chipMin = 0, scope = null, at = () => scope ?? "", source = () => scope === null ? void 0 : scope === "" ? { presets: controls.presets, variants: controls.variants } : controls.scopes[scope], unpinned = (values) => {
1033
1033
  let out;
1034
1034
  for (let k of Object.keys(values))
1035
1035
  if (controls.scopeOf(k) !== at() && !same(values[k], controls.locked[k]))
@@ -1142,10 +1142,15 @@ function createPresetStrip(doc, controls, showVariants, run, onAfterChange, pres
1142
1142
  return;
1143
1143
  }
1144
1144
  lastVariantsRef = variantsRef;
1145
- let nextEntries = buildEntries(), nextSig = JSON.stringify([scope, nextEntries.map((e) => [e.id, e.label])]);
1145
+ let nextEntries = buildEntries(), nextSig = JSON.stringify([scope, digits, nextEntries.map((e) => [e.id, e.label])]);
1146
1146
  if (entries = nextEntries, syncShown(), nextSig !== signature)
1147
1147
  signature = nextSig, entries = nextEntries, buttons = entries.map((entry, idx) => {
1148
- let b = el("button", "knobs-preset-chip", entry.label);
1148
+ let b = el("button", "knobs-preset-chip");
1149
+ if (digits && idx < 9) {
1150
+ let key = el("span", "knobs-preset-key", String(idx + 1));
1151
+ key.setAttribute("aria-hidden", "true"), b.append(key, el("span", "knobs-preset-label", entry.label)), b.setAttribute("aria-keyshortcuts", String(idx + 1));
1152
+ } else
1153
+ b.textContent = entry.label;
1149
1154
  return b.type = "button", b.tabIndex = -1, b.dataset.presetId = entry.id, b.dataset.presetKind = entry.kind, b.dataset.presetName = entry.label, b.setAttribute("role", "radio"), b.setAttribute("aria-label", entry.label), b.onclick = (e) => {
1150
1155
  if (e.preventDefault(), focusQuietly(), idx !== activeState.activeIndex || activeState.drifted)
1151
1156
  selectAt(idx);
@@ -1339,6 +1344,13 @@ function createPresetStrip(doc, controls, showVariants, run, onAfterChange, pres
1339
1344
  if (display = mode, placeDisplay())
1340
1345
  measurePill(!0);
1341
1346
  },
1347
+ digits(on) {
1348
+ if (digits === on)
1349
+ return;
1350
+ if (digits = on, root.toggleAttribute("data-digits", on), signature === "")
1351
+ return;
1352
+ signature = "", update();
1353
+ },
1342
1354
  save: () => {
1343
1355
  let message = "";
1344
1356
  return run(() => message = save()), message;
@@ -4022,6 +4034,111 @@ class GpuOverlayManager {
4022
4034
  let more = o.more;
4023
4035
  d[b + 40] = more ? more[0] : 0, d[b + 41] = more ? more[1] : 0, d[b + 42] = more ? more[2] : 0, d[b + 43] = more ? more[3] : 0;
4024
4036
  }
4037
+ drawPresetStrip(ps, tokens, clip, hinting, reducedMotion, dt, tray) {
4038
+ let moving = !1, psHovered = this.curPanelHovered && ps.element.matches(":hover");
4039
+ this.curSubHovered = psHovered;
4040
+ let psRect = this.rectOf(ps.element), trackRect = this.rectOf(ps.track);
4041
+ if (tray && !tokens.boxed)
4042
+ this.pushPrim({
4043
+ x: psRect.left,
4044
+ y: psRect.top,
4045
+ w: psRect.width,
4046
+ h: psRect.height,
4047
+ color: tokens.segBg,
4048
+ color2: tokens.accent,
4049
+ radius: tokens.radius,
4050
+ glowOrBlur: tokens.glowStrength * 8,
4051
+ kind: 1,
4052
+ p0: psHovered || this.isFocused(ps.element) ? 0.4 : 0
4053
+ });
4054
+ let stripClip = intersectClip(clip, [psRect.left, psRect.top, psRect.right, psRect.bottom]), activeState = ps.getActiveState(), chipButtons = ps.getButtons();
4055
+ if (tokens.boxed)
4056
+ for (let btn of chipButtons) {
4057
+ let br = this.rectOf(btn);
4058
+ if (br.right < stripClip[0] || br.left > stripClip[2])
4059
+ continue;
4060
+ this.drawButtonBox(btn, br, this.isHovered(btn), this.missed(btn, hinting), stripClip);
4061
+ }
4062
+ let activeBtn = activeState.activeIndex >= 0 ? chipButtons[activeState.activeIndex] : void 0, pe = ps.pillEdges, activeBtnRect = activeBtn ? this.rectOf(activeBtn) : void 0, panned = livePill(ps.track);
4063
+ if (activeBtn && activeBtnRect && !activeState.isCustom) {
4064
+ let left = activeBtnRect.left - trackRect.left, right = left + Math.max(20, activeBtnRect.width), top = activeBtnRect.top - trackRect.top;
4065
+ if (this.carry(pe, activeBtn, left, right, ps.pillY, top), panned)
4066
+ pe.snap(panned.left, panned.right), ps.pillY.snap(panned.top);
4067
+ else if (reducedMotion || pe.end.x - pe.start.x <= 1)
4068
+ pe.snap(left, right), ps.pillY.snap(top);
4069
+ else
4070
+ pe.to(left, right, 0, trailScale(tokens.blurStrength)), ps.pillY.set(top);
4071
+ ps.pillAlpha.set(activeState.drifted ? DRIFTED_PILL : 1);
4072
+ } else
4073
+ ps.pillAlpha.set(0);
4074
+ for (let sp of [pe.start, pe.end, ps.pillY, ps.pillAlpha])
4075
+ if (reducedMotion)
4076
+ sp.snap(sp.target);
4077
+ else if (sp.step(dt), !sp.resting)
4078
+ moving = !0;
4079
+ let pillAlpha = clamp(ps.pillAlpha.x, 0, 1);
4080
+ if (pillAlpha > 0.01)
4081
+ this.pushPrim({
4082
+ x: trackRect.left + pe.start.x,
4083
+ y: trackRect.top + ps.pillY.x,
4084
+ w: Math.max(18, pe.end.x - pe.start.x),
4085
+ h: Math.max(16, activeBtnRect?.height ?? trackRect.height),
4086
+ clip: stripClip,
4087
+ color: withAlpha(tokens.pillBg, pillAlpha),
4088
+ color2: withAlpha(tokens.pillBorder, pillAlpha),
4089
+ strokeWidth: this.hairline(tokens),
4090
+ aux2: withAlpha(tokens.rim, tokens.rim[3] * pillAlpha),
4091
+ radius: tokens.buttonRadius ?? tokens.radiusMd,
4092
+ glowOrBlur: tokens.glowStrength,
4093
+ kind: 3,
4094
+ blurX: reducedMotion ? 0 : clamp(pe.velocity * 0.006 * tokens.motionBlur, -8, 8)
4095
+ });
4096
+ for (let i = 0;i < chipButtons.length; i++) {
4097
+ let btn = chipButtons[i], br = this.rectOf(btn);
4098
+ if (br.right < stripClip[0] || br.left > stripClip[2])
4099
+ continue;
4100
+ let isActive = i === activeState.activeIndex, chipHovered = this.isHovered(btn);
4101
+ if (chipHovered)
4102
+ this.curSubHovered = !1;
4103
+ let mark = this.ease(btn, "dot", btn.hasAttribute("data-drifted") ? 1 : 0);
4104
+ if (mark > 0.01) {
4105
+ let size = 4 * (0.4 + 0.6 * mark);
4106
+ this.pushPrim({
4107
+ x: br.right - 6 - size / 2,
4108
+ y: br.top + 6 - size / 2,
4109
+ w: size,
4110
+ h: size,
4111
+ clip: stripClip,
4112
+ color: withAlpha(tokens.modified, 0.95 * mark),
4113
+ glowOrBlur: 0.5,
4114
+ kind: 7
4115
+ });
4116
+ }
4117
+ if (btn.hasAttribute("data-naming"))
4118
+ continue;
4119
+ let key = btn.querySelector(".knobs-preset-key"), name = key && btn.querySelector(".knobs-preset-label");
4120
+ if (key && name) {
4121
+ let kr = this.rectOf(key);
4122
+ this.drawText(key.textContent ?? "", kr.left, br.top + br.height * 0.5, withAlpha(tokens.dim, this.missed(btn, hinting)), { px: tokens.textMeta, weight: tokens.labelWeight, clip: stripClip });
4123
+ }
4124
+ let nr = name ? this.rectOf(name) : void 0;
4125
+ this.drawText(name ? name.textContent ?? "" : btn.textContent ?? "", nr ? nr.left : br.left + br.width * 0.5, br.top + br.height * 0.5, withAlpha(this.hot(btn, isActive || chipHovered, tokens.buttonColor ?? tokens.label), this.missed(btn, hinting)), {
4126
+ px: tokens.buttonFontSize ?? tokens.textControl,
4127
+ weight: isActive ? tokens.titleWeight : tokens.labelWeight,
4128
+ align: nr ? "left" : "center",
4129
+ clip: stripClip
4130
+ });
4131
+ }
4132
+ if (ps.saveButton && !ps.saveButton.hidden) {
4133
+ let sr = this.rectOf(ps.saveButton), hot = this.isHovered(ps.saveButton);
4134
+ this.drawText("+", sr.left + sr.width * 0.5, sr.top + sr.height * 0.5, this.hot(ps.saveButton, hot, tokens.dim), {
4135
+ px: tokens.textTitle,
4136
+ weight: 400,
4137
+ align: "center"
4138
+ });
4139
+ }
4140
+ return moving;
4141
+ }
4025
4142
  hairline(tokens) {
4026
4143
  return Math.max(1, Math.round(tokens.rimWidth * this.curScale)) / this.curScale;
4027
4144
  }
@@ -5768,7 +5885,6 @@ class GpuOverlayManager {
5768
5885
  this.placeBackdrop(panel);
5769
5886
  continue;
5770
5887
  }
5771
- let pillFill = tokens.pillBg;
5772
5888
  if (pageB)
5773
5889
  this.placeBackdrop(panel);
5774
5890
  let covers = drawn.some((r) => r.left < card.right && r.right > card.left && r.top < card.bottom && r.bottom > card.top);
@@ -5900,111 +6016,8 @@ class GpuOverlayManager {
5900
6016
  }
5901
6017
  }
5902
6018
  let ps = panel.presetStrip, hinting = panel.root.classList.contains("knobs-hinting"), stripAlpha = this.curAlpha;
5903
- if (!ps.element.hidden) {
5904
- this.curAlpha = stripAlpha * this.presence(ps.element);
5905
- let psHovered = this.curPanelHovered && ps.element.matches(":hover");
5906
- this.curSubHovered = psHovered;
5907
- let psRect = this.rectOf(ps.element), trackRect = this.rectOf(ps.track);
5908
- if (!tokens.boxed)
5909
- this.pushPrim({
5910
- x: psRect.left,
5911
- y: psRect.top,
5912
- w: psRect.width,
5913
- h: psRect.height,
5914
- color: tokens.segBg,
5915
- color2: tokens.accent,
5916
- radius: tokens.radius,
5917
- glowOrBlur: tokens.glowStrength * 8,
5918
- kind: 1,
5919
- p0: psHovered || this.isFocused(ps.element) ? 0.4 : 0
5920
- });
5921
- let stripClip = intersectClip(bodyClip, [
5922
- psRect.left,
5923
- psRect.top,
5924
- psRect.right,
5925
- psRect.bottom
5926
- ]), activeState = ps.getActiveState(), chipButtons = ps.getButtons();
5927
- if (tokens.boxed)
5928
- for (let btn of chipButtons) {
5929
- let br = this.rectOf(btn);
5930
- if (br.right < stripClip[0] || br.left > stripClip[2])
5931
- continue;
5932
- this.drawButtonBox(btn, br, this.isHovered(btn), this.missed(btn, hinting), stripClip);
5933
- }
5934
- let activeBtn = activeState.activeIndex >= 0 ? chipButtons[activeState.activeIndex] : void 0, pe = ps.pillEdges, activeBtnRect = activeBtn ? this.rectOf(activeBtn) : void 0, panned = livePill(ps.track);
5935
- if (activeBtn && activeBtnRect && !activeState.isCustom) {
5936
- let left = activeBtnRect.left - trackRect.left, right = left + Math.max(20, activeBtnRect.width), top = activeBtnRect.top - trackRect.top;
5937
- if (this.carry(pe, activeBtn, left, right, ps.pillY, top), panned)
5938
- pe.snap(panned.left, panned.right), ps.pillY.snap(panned.top);
5939
- else if (reducedMotion || pe.end.x - pe.start.x <= 1)
5940
- pe.snap(left, right), ps.pillY.snap(top);
5941
- else
5942
- pe.to(left, right, 0, trailScale(tokens.blurStrength)), ps.pillY.set(top);
5943
- ps.pillAlpha.set(activeState.drifted ? DRIFTED_PILL : 1);
5944
- } else
5945
- ps.pillAlpha.set(0);
5946
- for (let sp of [pe.start, pe.end, ps.pillY, ps.pillAlpha])
5947
- if (reducedMotion)
5948
- sp.snap(sp.target);
5949
- else if (sp.step(dt), !sp.resting)
5950
- anyMoving = !0;
5951
- let pillAlpha = clamp(ps.pillAlpha.x, 0, 1);
5952
- if (pillAlpha > 0.01)
5953
- this.pushPrim({
5954
- x: trackRect.left + pe.start.x,
5955
- y: trackRect.top + ps.pillY.x,
5956
- w: Math.max(18, pe.end.x - pe.start.x),
5957
- h: Math.max(16, activeBtnRect?.height ?? trackRect.height),
5958
- clip: stripClip,
5959
- color: withAlpha(pillFill, pillAlpha),
5960
- color2: withAlpha(tokens.pillBorder, pillAlpha),
5961
- strokeWidth: this.hairline(tokens),
5962
- aux2: withAlpha(tokens.rim, tokens.rim[3] * pillAlpha),
5963
- radius: tokens.buttonRadius ?? tokens.radiusMd,
5964
- glowOrBlur: tokens.glowStrength,
5965
- kind: 3,
5966
- blurX: reducedMotion ? 0 : clamp(pe.velocity * 0.006 * tokens.motionBlur, -8, 8)
5967
- });
5968
- for (let i = 0;i < chipButtons.length; i++) {
5969
- let btn = chipButtons[i], br = this.rectOf(btn);
5970
- if (br.right < stripClip[0] || br.left > stripClip[2])
5971
- continue;
5972
- let isActive = i === activeState.activeIndex, chipHovered = this.isHovered(btn);
5973
- if (chipHovered)
5974
- this.curSubHovered = !1;
5975
- let mark = this.ease(btn, "dot", btn.hasAttribute("data-drifted") ? 1 : 0);
5976
- if (mark > 0.01) {
5977
- let size = 4 * (0.4 + 0.6 * mark);
5978
- this.pushPrim({
5979
- x: br.right - 6 - size / 2,
5980
- y: br.top + 6 - size / 2,
5981
- w: size,
5982
- h: size,
5983
- clip: stripClip,
5984
- color: withAlpha(tokens.modified, 0.95 * mark),
5985
- glowOrBlur: 0.5,
5986
- kind: 7
5987
- });
5988
- }
5989
- if (btn.hasAttribute("data-naming"))
5990
- continue;
5991
- this.drawText(btn.textContent ?? "", br.left + br.width * 0.5, br.top + br.height * 0.5, withAlpha(this.hot(btn, isActive || chipHovered, tokens.buttonColor ?? tokens.label), this.missed(btn, hinting)), {
5992
- px: tokens.buttonFontSize ?? tokens.textControl,
5993
- weight: isActive ? tokens.titleWeight : tokens.labelWeight,
5994
- align: "center",
5995
- clip: stripClip
5996
- });
5997
- }
5998
- if (ps.saveButton && !ps.saveButton.hidden) {
5999
- let sr = this.rectOf(ps.saveButton), hot = this.isHovered(ps.saveButton);
6000
- this.drawText("+", sr.left + sr.width * 0.5, sr.top + sr.height * 0.5, this.hot(ps.saveButton, hot, tokens.dim), {
6001
- px: tokens.textTitle,
6002
- weight: 400,
6003
- align: "center"
6004
- });
6005
- }
6006
- this.curAlpha = stripAlpha;
6007
- }
6019
+ if (!ps.element.hidden)
6020
+ this.curAlpha = stripAlpha * this.presence(ps.element), anyMoving = this.drawPresetStrip(ps, tokens, bodyClip, hinting, reducedMotion, dt, !0) || anyMoving, this.curAlpha = stripAlpha;
6008
6021
  let tabs = panel.tabs;
6009
6022
  if (tabs && !tabs.element.hidden)
6010
6023
  anyMoving = this.drawTabStrip(tabs, hinting, reducedMotion, dt, {
@@ -6225,6 +6238,13 @@ class GpuOverlayManager {
6225
6238
  this.drawScope(card, cr, tokens.radius, 1);
6226
6239
  }
6227
6240
  }
6241
+ for (let gs of panel.groupStrips?.() ?? []) {
6242
+ let card = gs.element.parentElement;
6243
+ if (!card || gs.element.closest("[hidden]"))
6244
+ continue;
6245
+ let cr = cardRects.get(card) ?? this.rectOf(card);
6246
+ this.curClip = clipToTile(card, intersectClip(bodyClip, [cr.left, cr.top, cr.right, cr.bottom])), this.curAlpha = panelAlpha * this.presence(card) * fadeOf(card), anyMoving = this.drawPresetStrip(gs, tokens, this.curClip, hinting, reducedMotion, dt, !1) || anyMoving;
6247
+ }
6228
6248
  this.curClip = bodyClip, this.curAlpha = panelAlpha;
6229
6249
  let washed = /* @__PURE__ */ new Set, rowsAlpha = this.curAlpha;
6230
6250
  for (let row of panel.rows) {
@@ -11311,7 +11331,7 @@ function presence(el, o = {}) {
11311
11331
  return !1;
11312
11332
  }), tune = (seconds, zeta) => {
11313
11333
  let reduced = reducedMotion(win);
11314
- spring.omega = 2 * Math.PI / (reduced ? FADE.duration : seconds), spring.zeta = reduced ? 1 : zeta;
11334
+ spring.omega = 2 * Math.PI / (reduced ? Math.min(FADE.duration, seconds) : seconds), spring.zeta = reduced ? 1 : zeta;
11315
11335
  };
11316
11336
  return render(), {
11317
11337
  show() {
@@ -15156,7 +15176,7 @@ function buildPanel(controls, host, options) {
15156
15176
  if (helpButton?.hidden)
15157
15177
  titleEl.title = `${titleEl.textContent ? `${titleEl.textContent}
15158
15178
  ` : ""}Press ${show("help")} for keyboard shortcuts`;
15159
- let presetLabel = (id, scope = "") => options.presetLabels?.[id] ?? (id === "default" ? options.defaultLabel : void 0) ?? controls.presetLabel(id, scope), presetStrip = createPresetStrip(doc, controls, showVariants, run, () => wakeGpu(), presetLabel, (entries) => presetsTouchTab(entries), () => stripScope()), tabStrip = createTabStrip(doc, (id, animate) => selectTab(id, animate)), activeTab, searchOptions = typeof options.search === "object" ? options.search : {}, chipTests = /* @__PURE__ */ new Map, search = options.search && !page ? createSearch(doc, {
15179
+ let presetLabel = (id, scope = "") => options.presetLabels?.[id] ?? (id === "default" ? typeof options.defaultLabel === "object" ? options.defaultLabel[scope] : options.defaultLabel : void 0) ?? controls.presetLabel(id, scope), hintReach = (typeof options.hints === "object" ? options.hints.reach : options.hints) ?? "page", stripDigitsShown = typeof options.hints === "object" && options.hints.digits === "always", presetStrip = createPresetStrip(doc, controls, showVariants, run, () => wakeGpu(), presetLabel, (entries) => presetsTouchTab(entries), () => stripScope()), tabStrip = createTabStrip(doc, (id, animate) => selectTab(id, animate)), activeTab, searchOptions = typeof options.search === "object" ? options.search : {}, chipTests = /* @__PURE__ */ new Map, search = options.search && !page ? createSearch(doc, {
15160
15180
  placeholder: searchOptions.placeholder ?? "Search",
15161
15181
  chips: (searchOptions.chips ?? ["modified"]).map((chip) => {
15162
15182
  if (chip === "modified")
@@ -15187,8 +15207,19 @@ function buildPanel(controls, host, options) {
15187
15207
  else if ((!header.hidden && header.dataset.leaving !== "true") !== any)
15188
15208
  reveal(header, any, () => wakeGpu());
15189
15209
  };
15190
- presetStrip.display(page ? "chips" : options.presetDisplay ?? "auto");
15191
- let allActions = [
15210
+ presetStrip.display(page ? "chips" : options.presetDisplay ?? "auto"), presetStrip.digits(stripDigitsShown);
15211
+ let groupStrips = /* @__PURE__ */ new Map, tabNamed = (id) => (options.tabs ?? []).some((t) => (typeof t === "string" ? t : t.id) === id) || Object.values(controls.schema).some((f) => f.tab === id), groupStripFor = (group) => {
15212
+ if (page || !Object.hasOwn(controls.scopes, group) || tabNamed(group))
15213
+ return;
15214
+ let strip = groupStrips.get(group);
15215
+ if (!strip)
15216
+ strip = createPresetStrip(doc, controls, showVariants, run, () => wakeGpu(), presetLabel, void 0, () => stripScope() === group ? null : group), strip.element.setAttribute("aria-label", `${groupTitle(group)} presets`), strip.display(options.presetDisplay ?? "auto"), strip.digits(stripDigitsShown), groupStrips.set(group, strip);
15217
+ return strip;
15218
+ }, updateStrips = () => {
15219
+ presetStrip.update();
15220
+ for (let strip of groupStrips.values())
15221
+ strip.update();
15222
+ }, allActions = [
15192
15223
  ...controls.actions ?? [],
15193
15224
  ...options.actions ?? []
15194
15225
  ], body = el("div"), tabMotion = tabTransition(body, root, () => wakeGpu()), pinnedBody = el("div");
@@ -15480,7 +15511,7 @@ function buildPanel(controls, host, options) {
15480
15511
  }
15481
15512
  let specs = [], placed = /* @__PURE__ */ new Set;
15482
15513
  for (let [key, field] of entries) {
15483
- if (field.kind === "choice" && field.variants && !controls.isPinned(key))
15514
+ if (field.kind === "choice" && field.variants && controls.inPresets(key))
15484
15515
  continue;
15485
15516
  let pair = field.kind === "knob" && field.spring ? halves.get(field.spring.id) : void 0;
15486
15517
  if (pair?.duration && pair.bounce && field.kind === "knob" && field.spring) {
@@ -16049,7 +16080,7 @@ function buildPanel(controls, host, options) {
16049
16080
  else
16050
16081
  runs.push({ group: r.group, pinned, rows: [r] });
16051
16082
  }
16052
- let free = blocks.filter((b) => !b.leaving), chosen = [], pinnedBlocks = /* @__PURE__ */ new Set, usedSubheads = /* @__PURE__ */ new Set;
16083
+ let free = blocks.filter((b) => !b.leaving), chosen = [], pinnedBlocks = /* @__PURE__ */ new Set, usedSubheads = /* @__PURE__ */ new Set, stripped = /* @__PURE__ */ new Set;
16053
16084
  for (let run of runs) {
16054
16085
  let at = free.findIndex((b) => b.group === run.group), block = at >= 0 ? free.splice(at, 1)[0] : newBlock(run.group);
16055
16086
  if (at < 0) {
@@ -16076,7 +16107,10 @@ function buildPanel(controls, host, options) {
16076
16107
  }
16077
16108
  under = name, nodes.push(r.row);
16078
16109
  }
16079
- if (arrange(block.card, nodes), animate && at >= 0) {
16110
+ let strip = run.group !== void 0 && !stripped.has(run.group) ? groupStripFor(run.group) : void 0;
16111
+ if (strip)
16112
+ stripped.add(run.group);
16113
+ if (arrange(block.card, strip ? [strip.element, ...nodes] : nodes), animate && at >= 0) {
16080
16114
  for (let r of run.rows)
16081
16115
  if (entering.has(r))
16082
16116
  motion.push({ node: r.row, show: !0 });
@@ -16212,7 +16246,7 @@ function buildPanel(controls, host, options) {
16212
16246
  let keys = rows.flatMap((r) => {
16213
16247
  let tab = tabOf(r);
16214
16248
  return !pinnedRow(r) && (tab === void 0 || tab === activeTab) ? r.keys.filter((k) => controls.scopeOf(k) === "") : [];
16215
- }), v = variantsOf(controls.schema, controls.isPinned);
16249
+ }), v = variantsOf(controls.schema, (key) => !controls.inPresets(key));
16216
16250
  if (v) {
16217
16251
  let tab = v.field.tab ?? (v.field.group !== void 0 ? groupTab(v.field.group) : void 0);
16218
16252
  if (tab === void 0 || tab === activeTab)
@@ -16247,7 +16281,7 @@ function buildPanel(controls, host, options) {
16247
16281
  writeSession(controls.id, { tab: id });
16248
16282
  tabStrip.select(id, animate);
16249
16283
  let focused = doc.activeElement;
16250
- if (presetStrip.update(), applyVisibility(animate ? "tab" : "instant"), focused && root.contains(focused) && focused.closest("[hidden],[data-leaving]"))
16284
+ if (updateStrips(), applyVisibility(animate ? "tab" : "instant"), focused && root.contains(focused) && focused.closest("[hidden],[data-leaving]"))
16251
16285
  tabStrip.focus({ preventScroll: !0, focusVisible: !1 });
16252
16286
  options.onTab?.(id), wakeGpu();
16253
16287
  }
@@ -16575,7 +16609,7 @@ function buildPanel(controls, host, options) {
16575
16609
  changedCount++;
16576
16610
  }
16577
16611
  let stagger = initialized ? cascade(changedCount) : 0, moving = initialized ? rows.filter(changed) : rows;
16578
- if (presetStrip.update(), batchMeasures(() => {
16612
+ if (updateStrips(), batchMeasures(() => {
16579
16613
  for (let row of moving)
16580
16614
  if (row.slider?.prime(), row.editor?.prime?.(), row.choice)
16581
16615
  primeSegPill(row.choice.seg, row.choice.buttons);
@@ -16707,13 +16741,14 @@ function buildPanel(controls, host, options) {
16707
16741
  if (s.label?.hasAttribute("data-foldable"))
16708
16742
  add(s.label, sectionTitle(s.name), () => s.label.focus(), s.label.firstElementChild);
16709
16743
  }
16710
- presetStrip.getEntries().forEach((entry, i) => {
16711
- let chip = presetStrip.getButtons()[i];
16712
- if (chip)
16713
- add(chip, entry.label, () => {
16714
- presetStrip.selectById(entry.id), presetStrip.element.focus({ preventScroll: !0 });
16715
- });
16716
- });
16744
+ for (let strip of [presetStrip, ...groupStrips.values()])
16745
+ strip.getEntries().forEach((entry, i) => {
16746
+ let chip = strip.getButtons()[i];
16747
+ if (chip)
16748
+ add(chip, entry.label, () => {
16749
+ strip.selectById(entry.id), strip.element.focus({ preventScroll: !0 });
16750
+ });
16751
+ });
16717
16752
  for (let b of root.querySelectorAll(page ? ".knobs-head-cmd, .knobs-group-head button:not(.knobs-group-die,.knobs-group-reset,.knobs-chips button), .knobs-custom-actions button, .knobs-preset-save" : ".knobs-head-cmd, .knobs-group-head button, .knobs-custom-actions button, .knobs-preset-save, .knobs-popover button"))
16718
16753
  add(b, b.dataset.hint ?? b.getAttribute("aria-label") ?? b.textContent ?? "", () => b.focus());
16719
16754
  let focusedHead = page ? doc.activeElement?.closest(".knobs-tile")?.querySelector(":scope > .knobs-group-head") : null, presetUi = focusedHead ? groupChips.get(focusedHead.dataset.group ?? "") : void 0;
@@ -16729,7 +16764,7 @@ function buildPanel(controls, host, options) {
16729
16764
  add(stop, label, () => stop.focus());
16730
16765
  }
16731
16766
  return targets;
16732
- }, unregisterHints = (options.hints ?? "page") === "page" && bound("hint") ? pageHints(doc).register(root, () => collectHintTargets().map((t) => ({
16767
+ }, unregisterHints = hintReach === "page" && bound("hint") ? pageHints(doc).register(root, () => collectHintTargets().map((t) => ({
16733
16768
  el: t.el,
16734
16769
  label: t.display,
16735
16770
  ...t.labelEl ? { labelEl: t.labelEl } : {},
@@ -16786,6 +16821,9 @@ function buildPanel(controls, host, options) {
16786
16821
  runs.push({ at: b.head, stops: shown([b.head]) });
16787
16822
  for (let sh of subheads.values())
16788
16823
  runs.push({ at: sh.el, stops: shown([sh.el]) });
16824
+ for (let gs of groupStrips.values())
16825
+ if (visible(gs.element))
16826
+ runs.push({ at: gs.element, stops: shown([gs.element]) });
16789
16827
  runs.push(...strips), runs.sort((a, b) => a.at.compareDocumentPosition(b.at) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
16790
16828
  for (let run of runs)
16791
16829
  list.push(...run.stops);
@@ -17164,6 +17202,9 @@ function buildPanel(controls, host, options) {
17164
17202
  return { el: sub, level: "row" };
17165
17203
  return { el: r.row.closest(".knobs-card > *") ?? r.row, level: "row" };
17166
17204
  }
17205
+ let strip = active.closest(".knobs-card > .knobs-presets");
17206
+ if (strip)
17207
+ return { el: strip, level: "row" };
17167
17208
  let card = cardOf(active);
17168
17209
  return card ? { el: card, level: "card" } : null;
17169
17210
  }, partName = (part, active) => part.querySelector(".knobs-strip-label")?.textContent || active?.getAttribute("aria-label") || part.getAttribute("aria-label") || "Editor", trailFor = (t, active) => {
@@ -17299,6 +17340,18 @@ function buildPanel(controls, host, options) {
17299
17340
  if (!r || r.row.closest("[data-disabled],[data-readonly]"))
17300
17341
  return;
17301
17342
  return optionsOf(r);
17343
+ }, groupStripAt = (node) => node ? [...groupStrips.values()].find((s) => s.element.contains(node)) : void 0, groupStripOptions = /* @__PURE__ */ new Map, optionsOfStrip = (strip) => {
17344
+ let o = groupStripOptions.get(strip);
17345
+ if (!o)
17346
+ o = {
17347
+ get count() {
17348
+ return strip.getEntries().length;
17349
+ },
17350
+ choose: (i) => strip.select(i),
17351
+ shown: () => strip.getButtons(),
17352
+ anchor: strip.element
17353
+ }, groupStripOptions.set(strip, o);
17354
+ return o;
17302
17355
  }, stripDigits = () => visible(presetStrip.element) && presetStrip.getEntries().length > 1, stripOptions = {
17303
17356
  get count() {
17304
17357
  return presetStrip.getEntries().length;
@@ -17307,7 +17360,12 @@ function buildPanel(controls, host, options) {
17307
17360
  shown: () => presetStrip.getButtons(),
17308
17361
  anchor: presetStrip.element
17309
17362
  }, stripOptionsAt = (node) => {
17310
- if (hintCtrl.isActive || !node || !stripDigits())
17363
+ if (hintCtrl.isActive || !node || stripDigitsShown)
17364
+ return;
17365
+ let own = groupStripAt(node);
17366
+ if (own)
17367
+ return visible(own.element) && own.getEntries().length > 1 && !own.nameField() ? optionsOfStrip(own) : void 0;
17368
+ if (!stripDigits())
17311
17369
  return;
17312
17370
  return (presetStrip.element.contains(node) || focusLevel(node) === "panel") && !presetStrip.nameField() ? stripOptions : void 0;
17313
17371
  }, pickOption = (event) => {
@@ -17486,9 +17544,9 @@ function buildPanel(controls, host, options) {
17486
17544
  return;
17487
17545
  }
17488
17546
  if (pressed("presets", event)) {
17489
- let direction = key === keys.presets[0] ? -1 : 1;
17490
- if (visible(presetStrip.element) && presetStrip.getEntries().length > 1)
17491
- presetStrip.cycle(direction);
17547
+ let direction = key === keys.presets[0] ? -1 : 1, strip = groupStripAt(target) ?? presetStrip;
17548
+ if (visible(strip.element) && strip.getEntries().length > 1)
17549
+ strip.cycle(direction);
17492
17550
  else if (!cycleTab(direction))
17493
17551
  return;
17494
17552
  event.preventDefault(), event.stopPropagation();
@@ -17514,6 +17572,8 @@ function buildPanel(controls, host, options) {
17514
17572
  event.preventDefault(), searchReturn = target, search.focus();
17515
17573
  return;
17516
17574
  }
17575
+ if (/^[1-9]$/.test(key) && groupStripAt(target))
17576
+ return;
17517
17577
  if (/^[1-9]$/.test(key)) {
17518
17578
  let group = page ? focusedGroup(target) : void 0;
17519
17579
  if (Boolean(group && groupChips.has(group))) {
@@ -17562,7 +17622,7 @@ function buildPanel(controls, host, options) {
17562
17622
  return;
17563
17623
  }
17564
17624
  if (pressed("save", event) && showVariants) {
17565
- event.preventDefault(), presetStrip.save();
17625
+ event.preventDefault(), (groupStripAt(target) ?? presetStrip).save();
17566
17626
  return;
17567
17627
  }
17568
17628
  let index = rowAt(target);
@@ -17935,6 +17995,7 @@ function buildPanel(controls, host, options) {
17935
17995
  ...undock ? {} : { headerDie: { button: randomButton, die } },
17936
17996
  locks: lockIcons,
17937
17997
  presetStrip,
17998
+ groupStrips: () => groupStrips.values(),
17938
17999
  tabs: tabStrip,
17939
18000
  groups: gpuGroups,
17940
18001
  cards,
@@ -18041,7 +18102,10 @@ function buildPanel(controls, host, options) {
18041
18102
  dropGpu(r);
18042
18103
  for (let c of groupChips.values())
18043
18104
  c.dispose();
18044
- presetStrip.dispose(), tabStrip.dispose(), tabMotion.finish(), doc.removeEventListener("keydown", onGlobalKey), layout?.dispose(), tileSizes.disconnect(), headSize.disconnect(), win?.removeEventListener("scroll", onScroll), win?.removeEventListener("scrollend", onScrollEnd);
18105
+ presetStrip.dispose();
18106
+ for (let strip of groupStrips.values())
18107
+ strip.dispose();
18108
+ tabStrip.dispose(), tabMotion.finish(), doc.removeEventListener("keydown", onGlobalKey), layout?.dispose(), tileSizes.disconnect(), headSize.disconnect(), win?.removeEventListener("scroll", onScroll), win?.removeEventListener("scrollend", onScrollEnd);
18045
18109
  for (let type of ["wheel", "touchstart", "keydown"])
18046
18110
  doc.removeEventListener(type, touched, !0);
18047
18111
  doc.removeEventListener("pointerdown", onPointerDown, !0);
@@ -6,7 +6,7 @@ import {
6
6
  writeSession,
7
7
  injectStyles,
8
8
  toggleLayer
9
- } from "./chunk-pdf3zy95.js";
9
+ } from "./chunk-bejz4qcg.js";
10
10
 
11
11
  // src/panel/attach.ts
12
12
  function attach(controls, element, options = {}) {
@@ -82,7 +82,7 @@ function attach(controls, element, options = {}) {
82
82
  return;
83
83
  loading = !0;
84
84
  try {
85
- let { createPanel } = await import("./chunk-mbhy4jg5.js");
85
+ let { createPanel } = await import("./chunk-49hkdggk.js");
86
86
  if (disposed || !controls.enabled || panel)
87
87
  return;
88
88
  if (panel = createPanel(controls, element, close, { restored, chip }), remember)