dsh-capability-panel 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -32,10 +32,10 @@ let react = require("react");
32
32
  react = __toESM(react);
33
33
  let react_jsx_runtime = require("react/jsx-runtime");
34
34
  react_jsx_runtime = __toESM(react_jsx_runtime);
35
- let __deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
36
- __deepseek_ai_dsh_client_ui_primitives = __toESM(__deepseek_ai_dsh_client_ui_primitives);
37
35
  let react_dom = require("react-dom");
38
36
  react_dom = __toESM(react_dom);
37
+ let __deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
38
+ __deepseek_ai_dsh_client_ui_primitives = __toESM(__deepseek_ai_dsh_client_ui_primitives);
39
39
 
40
40
  //#region src/wire.ts
41
41
  const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
@@ -49,6 +49,7 @@ function parseSkillEntry(value) {
49
49
  const description = optString(value["description"]);
50
50
  const path = optString(value["path"]);
51
51
  const group = optString(value["group"]);
52
+ const fileAddress = optString(value["fileAddress"]);
52
53
  return {
53
54
  name: value["name"],
54
55
  state,
@@ -58,6 +59,7 @@ function parseSkillEntry(value) {
58
59
  provider: value["provider"],
59
60
  ...description === void 0 ? {} : { description },
60
61
  ...path === void 0 ? {} : { path },
62
+ ...fileAddress === void 0 ? {} : { fileAddress },
61
63
  ...group === void 0 ? {} : { group }
62
64
  };
63
65
  }
@@ -372,314 +374,93 @@ const MCP_TOOL_ROOT_CLASS = "ci-toolrow";
372
374
  const ROW_HEADER_CLASS = "ci-row-head";
373
375
 
374
376
  //#endregion
375
- //#region src/client/locale.ts
377
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/safeReact.mjs
376
378
  /**
377
- * Panel copy, bilingual. Chinese is the authoring language; English is the
378
- * fallback the host's locale runtime consults after the active locale misses
379
- * a key (and the locale a browser naming neither shipped language lands on).
379
+ * A clone of the React namespace for reading APIs that may be missing in older
380
+ * supported React versions. Bundlers can rewrite direct `React.someNewApi`
381
+ * reads into named imports, which breaks React 17. Reading from this cloned
382
+ * object keeps those lookups optional.
380
383
  *
381
- * The dictionaries register into the host's locale service (`ctx.locale`)
382
- * under this plugin's own namespace, so the panel follows the same language
383
- * switch as the rest of the UI. Templates interpolate `{name}` placeholders.
384
+ * @see https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
385
+ */
386
+ const SafeReact = { ...react };
387
+
388
+ //#endregion
389
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useRefWithInit.mjs
390
+ const UNINITIALIZED = {};
391
+ /**
392
+ * A React.useRef() that is initialized with a function. Note that it accepts an optional
393
+ * initialization argument, so the initialization function doesn't need to be an inline closure.
384
394
  *
385
- * tests/client/locale.spec.ts pins the two dictionaries to identical key sets
386
- * and checks every key the component looks up exists in both.
395
+ * @usage
396
+ * const ref = useRefWithInit(sortColumns, columns)
387
397
  */
388
- const LOCALE_NS = "capability-panel";
389
- const zh = {
390
- "state.loaded": "已加载",
391
- "state.pruned": "已截断",
392
- "state.evicted": "已挤出",
393
- "state.unloaded": "未加载",
394
- "blocked.count": "拦截 ×{count}",
395
- "action.enable": "开启 {name}",
396
- "action.disable": "关闭 {name}",
397
- "action.insert": "把 /{name} 填入输入框",
398
- "server.tools": "{count} 工具",
399
- "server.tool.one": "1 个工具",
400
- "server.unavailable": "无已注册工具",
401
- "server.unavailableHint": "宿主配置里声明了这个服务器,但它当前没有注册任何工具。原因无法从面板判定(服务未启动、正在重连、或本就没有工具都可能)。若它是个本地按需服务,先把程序开起来。",
402
- "action.reload": "重载 {name}",
403
- "action.reload.label": "重载",
404
- "action.reload.ing": "正在重载 {name}…",
405
- "action.reloadHint": "重新加载该服务器的插件实例(等同一次热重载):会断开并重连。对 stdio 类型的服务,这会重启其子进程。",
406
- "action.reload.failed": "重载 {name} 失败:{error}",
407
- "status.loading": "读取中…",
408
- "status.error": "读取失败:{error}(可尝试刷新页面;宿主改动需重启 dsh 后生效)",
409
- "empty.match": "无匹配项",
410
- "empty.skills": "无可用技能",
411
- "empty.mcp": "无 MCP 服务器",
412
- "empty.system": "无系统工具",
413
- "group.skills": "技能 ({shown}/{total})",
414
- "group.mcp": "MCP ({shown}/{total})",
415
- "group.system": "系统工具 ({shown}/{total})",
416
- "group.systemTools": "系统工具",
417
- "group.count": "{shown}/{total}",
418
- "tab.all": "全部",
419
- "tab.skills": "技能",
420
- "tab.mcp": "MCP",
421
- "tab.system": "工具",
422
- "tab.system.aria": "系统工具 {count}",
423
- "tabs.aria": "能力分区",
424
- "trigger.tooltip": "会话上下文:技能、MCP 与工具",
425
- "panel.aria": "会话上下文",
426
- "filter.placeholder": "筛选名称或描述…",
427
- "filter.aria": "筛选技能与工具",
428
- "filter.clear": "清空筛选",
429
- "filter.count": "匹配 {shown} / {total} 项",
430
- "footer.feedback": "反馈问题",
431
- "footer.feedbackHint": "在 GitHub 上打开能力面板的 issue 页",
432
- "footer.openSettings": "全局配置",
433
- "footer.openSettingsHint": "打开设置并进入「能力面板」页",
434
- "disclosure.expand": "展开 {subject} 的{detail}",
435
- "disclosure.collapse": "收起 {subject} 的{detail}",
436
- "disclosure.pinned": "{subject} 的{detail}(筛选时保持展开)",
437
- "detail.description": "描述",
438
- "detail.tools": "工具",
439
- "preset.nav": "能力面板",
440
- "preset.title": "能力面板",
441
- "preset.intro": "设置每个 Agent preset 的默认能力集合,之后新建或恢复的会话会继承它。输入框里的「会话上下文」只改当前会话,并随该会话在重启后恢复。",
442
- "preset.projectSkill": "当前项目",
443
- "preset.kindAria": "按类别筛选",
444
- "preset.readonly": "当前设置存储不可写;你可以查看工具,但无法保存微调。",
445
- "preset.choose": "Agent preset",
446
- "preset.empty": "没有可用的 Agent preset。",
447
- "preset.noTools": "这个 preset 没有可用能力。",
448
- "preset.reserved": "{name} 是保留的传输通道,不能关闭。",
449
- "preset.broken": "这个 preset 无法组装会话:{reason}。修好它之后才能列出工具。",
450
- "degraded.item": "⚠ 部分读取失败:{note}",
451
- "source.project-dsh": "项目 .dsh",
452
- "source.project-agents": "项目 agent",
453
- "source.runtime": "运行时",
454
- "source.user-dsh": "用户 .dsh",
455
- "source.user-agents": "用户 agent",
456
- "source.custom": "自定义",
457
- "source.bundled": "内置",
458
- "source.host": "全局",
459
- "source.preset": "预设",
460
- "source.openFolder": "在文件管理器中打开 {source}"
461
- };
462
- const en = {
463
- "state.loaded": "loaded",
464
- "state.pruned": "truncated",
465
- "state.evicted": "evicted",
466
- "state.unloaded": "not loaded",
467
- "blocked.count": "blocked ×{count}",
468
- "action.enable": "Enable {name}",
469
- "action.disable": "Disable {name}",
470
- "action.insert": "Insert /{name} into the composer",
471
- "server.tools": "{count} tools",
472
- "server.tool.one": "1 tool",
473
- "server.unavailable": "no tools registered",
474
- "server.unavailableHint": "This host declares the server, but it currently registers no tools. The panel cannot tell why (service not started, mid-reconnect, or genuinely tool-less are all possible). If it is a local on-demand service, start its program first.",
475
- "action.reload": "Reload {name}",
476
- "action.reload.label": "Reload",
477
- "action.reload.ing": "Reloading {name}…",
478
- "action.reloadHint": "Reload this server’s plugin instance (equivalent to one hot reload): it disconnects and reconnects. For a stdio service this restarts its child process.",
479
- "action.reload.failed": "Failed to reload {name}: {error}",
480
- "status.loading": "Loading…",
481
- "status.error": "Failed to load: {error} (try refreshing the page; host changes take effect after a dsh restart)",
482
- "empty.match": "No matches",
483
- "empty.skills": "No skills available",
484
- "empty.mcp": "No MCP servers",
485
- "empty.system": "No system tools",
486
- "group.skills": "Skills ({shown}/{total})",
487
- "group.mcp": "MCP ({shown}/{total})",
488
- "group.system": "System tools ({shown}/{total})",
489
- "group.systemTools": "System tools",
490
- "group.count": "{shown}/{total}",
491
- "tab.all": "All",
492
- "tab.skills": "Skills",
493
- "tab.mcp": "MCP",
494
- "tab.system": "Tools",
495
- "tab.system.aria": "System tools, {count}",
496
- "tabs.aria": "Capability sections",
497
- "trigger.tooltip": "Session context: skills, MCP & tools",
498
- "panel.aria": "Session context",
499
- "filter.placeholder": "Filter by name or description…",
500
- "filter.aria": "Filter skills and tools",
501
- "filter.clear": "Clear filter",
502
- "filter.count": "{shown} / {total} matched",
503
- "footer.feedback": "Report an issue",
504
- "footer.feedbackHint": "Open the capability panel’s issues on GitHub",
505
- "footer.openSettings": "Global settings",
506
- "footer.openSettingsHint": "Open Settings on the Capability Panel page",
507
- "disclosure.expand": "Expand {detail} for {subject}",
508
- "disclosure.collapse": "Collapse {detail} for {subject}",
509
- "disclosure.pinned": "{detail} for {subject} (kept open while filtering)",
510
- "detail.description": "description",
511
- "detail.tools": "tools",
512
- "preset.nav": "Capability Panel",
513
- "preset.title": "Capability Panel",
514
- "preset.intro": "Choose the default capabilities each agent preset starts from; sessions created or resumed afterward inherit it. The composer's Session context changes only the current session, and stays with it across restarts.",
515
- "preset.projectSkill": "this project",
516
- "preset.kindAria": "Filter by category",
517
- "preset.readonly": "Settings storage is read-only. You can inspect tools, but changes cannot be saved.",
518
- "preset.choose": "Agent preset",
519
- "preset.empty": "No agent presets are available.",
520
- "preset.noTools": "This preset exposes no capabilities.",
521
- "preset.reserved": "{name} is a reserved transport and cannot be disabled.",
522
- "preset.broken": "This preset cannot compose a session: {reason}. Fix it before its tools can be listed.",
523
- "degraded.item": "⚠ Partial read failed: {note}",
524
- "source.project-dsh": "project .dsh",
525
- "source.project-agents": "project agent",
526
- "source.runtime": "runtime",
527
- "source.user-dsh": "user .dsh",
528
- "source.user-agents": "user agent",
529
- "source.custom": "custom",
530
- "source.bundled": "bundled",
531
- "source.host": "global",
532
- "source.preset": "preset",
533
- "source.openFolder": "Open {source} in file manager"
534
- };
398
+ function useRefWithInit(init, initArg) {
399
+ const ref = react.useRef(UNINITIALIZED);
400
+ if (ref.current === UNINITIALIZED) ref.current = init(initArg);
401
+ return ref;
402
+ }
403
+
404
+ //#endregion
405
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useStableCallback.mjs
406
+ const useInsertionEffect = SafeReact.useInsertionEffect;
407
+ const useSafeInsertionEffect = useInsertionEffect && useInsertionEffect !== SafeReact.useLayoutEffect ? useInsertionEffect : (fn) => fn();
535
408
  /**
536
- * Register both dictionaries as one effect: the single-locale form is the
537
- * documented entry for namespaces outside the host's compile-time merge
538
- * table, and the returned disposers release both on unload.
409
+ * Stabilizes the function passed so it's always the same between renders.
410
+ *
411
+ * The function becomes non-reactive to any values it captures.
412
+ * It can safely be passed as a dependency of `React.useMemo` and `React.useEffect` without re-triggering them if its captured values change.
413
+ *
414
+ * The function must only be called inside effects and event handlers, never during render (which throws an error).
415
+ *
416
+ * This hook is a more permissive version of React 19.2's `React.useEffectEvent` in that it can be passed through contexts and called in event handler props, not just effects.
539
417
  */
540
- function registerLocale(locale) {
541
- const disposeZh = locale.register(LOCALE_NS, "zh", zh);
542
- const disposeEn = locale.register(LOCALE_NS, "en", en);
543
- return () => {
544
- disposeZh();
545
- disposeEn();
418
+ function useStableCallback(callback) {
419
+ const stable = useRefWithInit(createStableCallback).current;
420
+ stable.next = callback;
421
+ useSafeInsertionEffect(stable.effect);
422
+ return stable.trampoline;
423
+ }
424
+ function createStableCallback() {
425
+ const stable = {
426
+ next: void 0,
427
+ callback: assertNotCalled,
428
+ trampoline: (...args) => stable.callback?.(...args),
429
+ effect: () => {
430
+ stable.callback = stable.next;
431
+ }
546
432
  };
433
+ return stable;
547
434
  }
435
+ function assertNotCalled() {}
548
436
 
549
437
  //#endregion
550
- //#region src/client/styles.ts
551
- const TOK = {
552
- textPrimary: "var(--dsw-alias-label-primary, #0f1115)",
553
- textSecondary: "var(--dsw-alias-label-secondary, #61666b)",
554
- textTertiary: "var(--dsw-alias-label-tertiary, #81858c)",
555
- border: "var(--dsw-alias-border-l1, rgba(0,0,0,.04))",
556
- borderStrong: "var(--dsw-alias-border-l2, rgba(0,0,0,.1))",
557
- switchOn: "var(--dsw-alias-state-business-primary, #4176e6)",
558
- switchOff: "var(--dsw-alias-border-l2, rgba(0,0,0,.1))",
559
- switchThumb: "var(--dsw-alias-bg-layer-1, #ffffff)",
560
- switchEase: "var(--ds-ease-in-out, cubic-bezier(.4, 0, .2, 1))",
561
- menuBg: "var(--dsw-specific-menu, #ffffff)",
562
- menuBorder: "var(--dsw-alias-border-inverted, rgba(0,0,0,.1))",
563
- menuShadow: "var(--dsw-shadow-lv3, 0 12px 32px rgba(0,0,0,.22))",
564
- menuBlur: "var(--dsw-menu-backdrop-filter, none)",
565
- bgBase: "var(--dsw-alias-bg-base, #ffffff)",
566
- fontFamily: "var(--dsw-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", \"Helvetica Neue\", Helvetica, Arial, sans-serif)",
567
- success: "var(--dsw-alias-state-success-primary, #22c55e)",
568
- warn: "var(--dsw-alias-state-warn-primary, #f59e0b)",
569
- error: "var(--dsw-alias-state-error-primary, #ec1313)",
570
- info: "var(--dsw-alias-state-business-primary, #4176e6)"
571
- };
572
- const PANEL_CSS = [
573
- ".ci-trigger:focus-visible,.ci-switch:focus-visible,.ci-iconbtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;border-radius:999px}",
574
- ".ci-disclosure-trigger:focus-visible,.ci-server-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;border-radius:4px}",
575
- ".ci-tab:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;border-radius:6px}",
576
- ".ci-trigger:hover,.ci-iconbtn:hover,.ci-server-trigger:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
577
- ".ci-switch:hover:not(:disabled){filter:brightness(1.12)}",
578
- ".ci-row-head{display:flex;align-items:center;gap:8px;padding:6px 8px;margin:0 -8px;border-radius:8px}",
579
- ".ci-row-head:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
580
- ".ci-row-head .ci-send{opacity:0;transition:opacity .12s}",
581
- ".ci-row-head:hover .ci-send,.ci-row-head:focus-within .ci-send{opacity:1}",
582
- ".ci-filter:focus{border-color:var(--dsw-alias-state-business-primary,#4176e6)}",
583
- ".ci-filter:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:0}",
584
- ".ci-filter::placeholder{color:var(--dsw-alias-label-tertiary,#81858c)}",
585
- ".ci-panel{transform-origin:var(--transform-origin);transition:opacity .14s var(--ds-ease-in-out,ease),transform .14s var(--ds-ease-in-out,ease)}",
586
- ".ci-panel[data-starting-style],.ci-panel[data-ending-style]{opacity:0;transform:scale(.96) translateY(4px)}",
587
- ".ci-collapse{height:var(--collapsible-panel-height);transition:height .14s var(--ds-ease-in-out,ease);overflow:hidden}",
588
- ".ci-collapse[data-starting-style],.ci-collapse[data-ending-style]{height:0}",
589
- ".ci-toolrow{content-visibility:auto;contain-intrinsic-size:auto 30px}",
590
- ".ci-disclosure-trigger{min-width:0;display:flex;align-items:center;gap:6px;flex:1 1 auto;padding:0;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}",
591
- ".ci-disclosure-trigger:disabled,.ci-server-trigger:disabled{cursor:default}",
592
- ".ci-disclosure-trigger:hover .ci-name{color:var(--dsw-alias-label-primary,#0f1115)}",
593
- ".ci-description{padding:3px 0 0 24px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858c);word-break:break-word}",
594
- ".ci-chevron{display:grid;place-items:center;width:18px;height:18px;flex:none;color:var(--dsw-alias-label-tertiary,#81858c);border-radius:4px}",
595
- ".ci-chevron svg{transition:transform .12s var(--ds-ease-in-out,ease)}",
596
- ".ci-server-trigger[aria-expanded=\"true\"] .ci-chevron svg,.ci-disclosure-trigger[aria-expanded=\"true\"] .ci-chevron svg,.ci-preset-part-trigger[aria-expanded=\"true\"] .ci-chevron svg{transform:rotate(90deg)}",
597
- ".ci-tabs{display:flex;gap:2px;padding:2px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
598
- ".ci-tab{flex:1;height:24px;border:none;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary,#61666b);font:inherit;font-size:12px;line-height:1;cursor:pointer;font-variant-numeric:tabular-nums;padding:0 4px}",
599
- ".ci-tab:hover{color:var(--dsw-alias-label-primary,#0f1115)}",
600
- ".ci-tab[data-active]{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#0f1115);box-shadow:var(--dsw-elevation-soft,0 1px 2px rgba(0,0,0,.08))}",
601
- ".ci-preset-section{width:100%;max-width:760px;color:var(--dsw-alias-label-primary,#0f1115);display:flex;flex-direction:column;gap:14px}",
602
- ".ci-settings-title{margin:0;color:var(--dsw-alias-label-primary,#0f1115);font-size:18px;font-weight:600;line-height:26px}",
603
- ".ci-settings-intro,.ci-settings-description,.ci-settings-note{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary,#81858c)}",
604
- ".ci-settings-note{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:8px}",
605
- ".ci-preset-toolbar{display:flex;gap:10px;align-items:center;margin:0}",
606
- ".ci-search{position:relative;flex:1 1 auto;min-width:180px;display:flex;align-items:center;color:var(--dsw-alias-label-tertiary,#81858c)}",
607
- ".ci-search>svg{position:absolute;left:12px;pointer-events:none}",
608
- ".ci-preset-filter{width:100%;height:36px;box-sizing:border-box;padding:0 34px 0 36px;border:.5px solid var(--dsw-alias-border-l4,rgba(0,0,0,.16));border-radius:var(--dsw-radius-md,12px);background-color:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-size:13px;font-weight:400;outline:none}",
609
- ".ci-preset-filter:focus-visible{border-color:var(--dsw-alias-state-business-primary,#4176e6);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-state-business-primary,#4176e6) 18%,transparent)}",
610
- ".ci-preset-part{display:flex;flex-direction:column;gap:10px;margin:0;padding:14px 0 0;border-top:.5px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}",
611
- ".ci-preset-part:first-of-type{border-top:0;padding-top:0}",
612
- ".ci-preset-part-trigger{display:flex;align-items:center;gap:8px;min-height:32px;padding:0;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}",
613
- ".ci-preset-part-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px;border-radius:4px}",
614
- ".ci-preset-part-title{margin:0;font-size:14px;font-weight:400;line-height:22px;color:var(--dsw-alias-label-primary,#0f1115)}",
615
- ".ci-preset-part-sub{margin:-4px 0 0 26px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858c);font-variant-numeric:tabular-nums}",
616
- ".ci-preset-badge{display:inline-block;margin-left:6px;padding:1px 6px;line-height:1.5;border-radius:999px;font-size:11px;font-weight:500;vertical-align:middle;background-color:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.05));color:var(--dsw-alias-label-tertiary,#81858c)}",
617
- ".ci-preset-group{padding:0}",
618
- ".ci-preset-server-trigger{display:flex;align-items:center;gap:8px;flex:1;min-width:0;background:none;border:none;padding:0;text-align:left;font:inherit;color:inherit;cursor:pointer}",
619
- ".ci-preset-server-trigger:disabled{cursor:default}",
620
- ".ci-preset-group .ci-preset-tool-list{margin:0;padding-left:26px}",
621
- ".ci-preset-picker-trigger{height:36px;display:inline-flex;align-items:center;gap:8px;padding:0 14px;border:none;border-radius:var(--dsw-radius-md,12px);background:var(--dsw-alias-bg-module-platform,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-size:14px;font-weight:400;line-height:22px;cursor:pointer;outline:none;max-width:280px;flex:none;white-space:nowrap}",
622
- ".ci-preset-picker-trigger:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
623
- ".ci-preset-picker-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px}",
624
- ".ci-preset-picker-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}",
625
- ".ci-preset-picker-chevron{color:var(--dsw-alias-label-tertiary,#81858c);flex:none;display:inline-grid;place-items:center;transition:transform .12s}",
626
- ".ci-preset-picker-chevron-open{transform:rotate(180deg)}",
627
- ".ci-settings-subtitle{margin:0 0 6px;color:var(--dsw-alias-label-primary,#0f1115);font-size:14px;line-height:22px}",
628
- ".ci-preset-tool-list{list-style:none;margin:0;padding:0}",
629
- ".ci-preset-tool-row{display:flex;align-items:center;gap:16px}",
630
- ".ci-preset-tool-copy{display:grid;min-width:0;flex:1}",
631
- ".ci-preset-tool-name{color:var(--dsw-alias-label-primary,#0f1115);font-weight:600;overflow-wrap:anywhere}",
632
- ".ci-preset-tool-description{color:var(--dsw-alias-label-tertiary,#81858c);line-height:18px;overflow-wrap:anywhere}",
633
- ".ci-preset-item{list-style:none}",
634
- ".ci-preset-disclosure{display:block}",
635
- ".ci-preset-spacer{width:18px;flex:none}",
636
- ".ci-preset-detail{padding:0 0 10px 24px;color:var(--dsw-alias-label-tertiary,#81858c);line-height:18px;overflow-wrap:anywhere}",
637
- ".ci-preset-kinds{margin:0}",
638
- ".ci-preset-kinds .ci-tabs{display:inline-flex}",
639
- ".ci-preset-kinds .ci-tab{flex:0 0 auto;padding:0 12px}",
640
- ".ci-source-header:hover .ci-folder-icon{opacity:1 !important}",
641
- ".ci-reconnect{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.14));background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-secondary,#61666b);border-radius:8px;padding:3px 9px;font-size:12px;line-height:1.4;cursor:pointer;font-family:inherit;flex:none}",
642
- ".ci-reconnect:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#0f1115)}",
643
- ".ci-reconnect:disabled{opacity:.7;cursor:default}",
644
- ".ci-reconnect:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px}",
645
- ".ci-reconnect-glyph{display:inline-grid;place-items:center;width:12px;height:12px}",
646
- ".ci-reconnect-busy .ci-reconnect-glyph{animation:ci-reconnect-spin .8s linear infinite}",
647
- "@keyframes ci-reconnect-spin{to{transform:rotate(360deg)}}",
648
- "@media (prefers-reduced-motion: reduce){.ci-reconnect-busy .ci-reconnect-glyph{animation:none}}",
649
- ".ci-source-divider{list-style:none}",
650
- ".ci-feedback-link{display:inline-flex;align-items:center;gap:4px;color:var(--dsw-alias-label-tertiary,#8a8f98);font-size:12px;line-height:18px;text-decoration:none;cursor:pointer}",
651
- ".ci-feedback-link:hover{color:var(--dsw-alias-label-primary,#0f1115);text-decoration:underline}",
652
- ".ci-feedback-link:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px;border-radius:3px}",
653
- ".ci-feedback-icon{display:inline-grid;place-items:center;flex:none}",
654
- ".ci-settings-link{border:0;background:none;padding:0;font-family:inherit}",
655
- "@media (prefers-reduced-motion: reduce){.ci-thumb,.ci-panel,.ci-collapse,.ci-chevron svg{transition:none !important}}"
656
- ].join("\n");
657
-
658
- //#endregion
659
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useControlled.mjs
660
- function useControlled({ controlled, default: defaultProp, name, state = "value" }) {
661
- const { current: isControlled } = react.useRef(controlled !== void 0);
662
- const [valueState, setValue] = react.useState(defaultProp);
663
- return [isControlled ? controlled : valueState, react.useCallback((newValue) => {
664
- if (!isControlled) setValue(newValue);
665
- }, [])];
666
- }
667
-
668
- //#endregion
669
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useRefWithInit.mjs
670
- const UNINITIALIZED = {};
438
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/formatErrorMessage.mjs
671
439
  /**
672
- * A React.useRef() that is initialized with a function. Note that it accepts an optional
673
- * initialization argument, so the initialization function doesn't need to be an inline closure.
674
- *
675
- * @usage
676
- * const ref = useRefWithInit(sortColumns, columns)
440
+ * Creates a formatErrorMessage function with a custom URL and prefix.
441
+ * @param baseUrl - The base URL for the error page (e.g., 'https://base-ui.com/production-error')
442
+ * @param prefix - The prefix for the error message (e.g., 'Base UI')
443
+ * @returns A function that formats error messages with the given URL and prefix
677
444
  */
678
- function useRefWithInit(init, initArg) {
679
- const ref = react.useRef(UNINITIALIZED);
680
- if (ref.current === UNINITIALIZED) ref.current = init(initArg);
681
- return ref;
445
+ function createFormatErrorMessage(baseUrl, prefix) {
446
+ return function formatErrorMessage$1(code, ...args) {
447
+ const url = new URL(baseUrl);
448
+ url.searchParams.set("code", code.toString());
449
+ args.forEach((arg) => url.searchParams.append("args[]", arg));
450
+ return `${prefix} error #${code}; visit ${url} for the full message.`;
451
+ };
682
452
  }
453
+ /**
454
+ * WARNING: Don't import this directly. It's imported by the code generated by
455
+ * `@mui/internal-babel-plugin-minify-errors`. Make sure to always use string literals in `Error`
456
+ * constructors to ensure the plugin works as expected. Supported patterns include:
457
+ * throw new Error('My message');
458
+ * throw new Error(`My message: ${foo}`);
459
+ * throw new Error(`My message: ${foo}` + 'another string');
460
+ * ...
461
+ */
462
+ const formatErrorMessage = createFormatErrorMessage("https://base-ui.com/production-error", "Base UI");
463
+ var formatErrorMessage_default = formatErrorMessage;
683
464
 
684
465
  //#endregion
685
466
  //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useMergedRefs.mjs
@@ -773,68 +554,6 @@ function update(forkRef, refs) {
773
554
  };
774
555
  }
775
556
 
776
- //#endregion
777
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useIsoLayoutEffect.mjs
778
- const noop = () => {};
779
- const useIsoLayoutEffect = typeof document !== "undefined" ? react.useLayoutEffect : noop;
780
-
781
- //#endregion
782
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/visuallyHidden.mjs
783
- const visuallyHiddenBase = {
784
- clipPath: "inset(50%)",
785
- overflow: "hidden",
786
- whiteSpace: "nowrap",
787
- border: 0,
788
- padding: 0,
789
- width: 1,
790
- height: 1,
791
- margin: -1
792
- };
793
- const visuallyHidden = {
794
- ...visuallyHiddenBase,
795
- position: "fixed",
796
- top: 0,
797
- left: 0
798
- };
799
- const visuallyHiddenInput = {
800
- ...visuallyHiddenBase,
801
- position: "absolute"
802
- };
803
-
804
- //#endregion
805
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/empty.mjs
806
- function NOOP() {}
807
- const EMPTY_ARRAY = Object.freeze([]);
808
- const EMPTY_OBJECT = Object.freeze({});
809
-
810
- //#endregion
811
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/formatErrorMessage.mjs
812
- /**
813
- * Creates a formatErrorMessage function with a custom URL and prefix.
814
- * @param baseUrl - The base URL for the error page (e.g., 'https://base-ui.com/production-error')
815
- * @param prefix - The prefix for the error message (e.g., 'Base UI')
816
- * @returns A function that formats error messages with the given URL and prefix
817
- */
818
- function createFormatErrorMessage(baseUrl, prefix) {
819
- return function formatErrorMessage$1(code, ...args) {
820
- const url = new URL(baseUrl);
821
- url.searchParams.set("code", code.toString());
822
- args.forEach((arg) => url.searchParams.append("args[]", arg));
823
- return `${prefix} error #${code}; visit ${url} for the full message.`;
824
- };
825
- }
826
- /**
827
- * WARNING: Don't import this directly. It's imported by the code generated by
828
- * `@mui/internal-babel-plugin-minify-errors`. Make sure to always use string literals in `Error`
829
- * constructors to ensure the plugin works as expected. Supported patterns include:
830
- * throw new Error('My message');
831
- * throw new Error(`My message: ${foo}`);
832
- * throw new Error(`My message: ${foo}` + 'another string');
833
- * ...
834
- */
835
- const formatErrorMessage = createFormatErrorMessage("https://base-ui.com/production-error", "Base UI");
836
- var formatErrorMessage_default = formatErrorMessage;
837
-
838
557
  //#endregion
839
558
  //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/reactVersion.mjs
840
559
  const majorVersion = parseInt(react.version, 10);
@@ -865,6 +584,12 @@ function mergeObjects(a, b) {
865
584
  };
866
585
  }
867
586
 
587
+ //#endregion
588
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/empty.mjs
589
+ function NOOP() {}
590
+ const EMPTY_ARRAY = Object.freeze([]);
591
+ const EMPTY_OBJECT = Object.freeze({});
592
+
868
593
  //#endregion
869
594
  //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/getStateAttributesProps.mjs
870
595
  function getStateAttributesProps(state, customMapping) {
@@ -1132,16 +857,14 @@ function renderTag(Tag, props) {
1132
857
  }
1133
858
 
1134
859
  //#endregion
1135
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/safeReact.mjs
1136
- /**
1137
- * A clone of the React namespace for reading APIs that may be missing in older
1138
- * supported React versions. Bundlers can rewrite direct `React.someNewApi`
1139
- * reads into named imports, which breaks React 17. Reading from this cloned
1140
- * object keeps those lookups optional.
1141
- *
1142
- * @see https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
1143
- */
1144
- const SafeReact = { ...react };
860
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useControlled.mjs
861
+ function useControlled({ controlled, default: defaultProp, name, state = "value" }) {
862
+ const { current: isControlled } = react.useRef(controlled !== void 0);
863
+ const [valueState, setValue] = react.useState(defaultProp);
864
+ return [isControlled ? controlled : valueState, react.useCallback((newValue) => {
865
+ if (!isControlled) setValue(newValue);
866
+ }, [])];
867
+ }
1145
868
 
1146
869
  //#endregion
1147
870
  //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useId.mjs
@@ -1184,1686 +907,2185 @@ function useBaseUiId(idOverride) {
1184
907
  }
1185
908
 
1186
909
  //#endregion
1187
- //#region node_modules/.pnpm/@floating-ui+utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs
1188
- function hasWindow() {
1189
- return typeof window !== "undefined";
1190
- }
1191
- function getNodeName(node) {
1192
- if (isNode(node)) return (node.nodeName || "").toLowerCase();
1193
- return "#document";
1194
- }
1195
- function getWindow(node) {
1196
- var _node$ownerDocument;
1197
- return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
1198
- }
1199
- function getDocumentElement(node) {
1200
- var _ref;
1201
- return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
1202
- }
1203
- function isNode(value) {
1204
- if (!hasWindow()) return false;
1205
- return value instanceof Node || value instanceof getWindow(value).Node;
1206
- }
1207
- function isElement(value) {
1208
- if (!hasWindow()) return false;
1209
- return value instanceof Element || value instanceof getWindow(value).Element;
1210
- }
1211
- function isHTMLElement(value) {
1212
- if (!hasWindow()) return false;
1213
- return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
1214
- }
1215
- function isShadowRoot(value) {
1216
- if (!hasWindow() || typeof ShadowRoot === "undefined") return false;
1217
- return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
1218
- }
1219
- function isOverflowElement(element) {
1220
- const { overflow, overflowX, overflowY, display } = getComputedStyle$1(element);
1221
- return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== "inline" && display !== "contents";
1222
- }
1223
- function isTableElement(element) {
1224
- return /^(table|td|th)$/.test(getNodeName(element));
1225
- }
1226
- function isTopLayer(element) {
1227
- try {
1228
- if (element.matches(":popover-open")) return true;
1229
- } catch (_e) {}
1230
- try {
1231
- return element.matches(":modal");
1232
- } catch (_e) {
1233
- return false;
1234
- }
1235
- }
1236
- const willChangeRe = /transform|translate|scale|rotate|perspective|filter/;
1237
- const containRe = /paint|layout|strict|content/;
1238
- const isNotNone = (value) => !!value && value !== "none";
1239
- let isWebKitValue;
1240
- function isContainingBlock(elementOrCss) {
1241
- const css = isElement(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss;
1242
- return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || "") || containRe.test(css.contain || "");
1243
- }
1244
- function getContainingBlock(element) {
1245
- let currentNode = getParentNode(element);
1246
- while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
1247
- if (isContainingBlock(currentNode)) return currentNode;
1248
- else if (isTopLayer(currentNode)) return null;
1249
- currentNode = getParentNode(currentNode);
1250
- }
1251
- return null;
1252
- }
1253
- function isWebKit() {
1254
- if (isWebKitValue == null) isWebKitValue = typeof CSS !== "undefined" && CSS.supports && CSS.supports("-webkit-backdrop-filter", "none");
1255
- return isWebKitValue;
1256
- }
1257
- function isLastTraversableNode(node) {
1258
- return /^(html|body|#document)$/.test(getNodeName(node));
1259
- }
1260
- function getComputedStyle$1(element) {
1261
- return getWindow(element).getComputedStyle(element);
1262
- }
1263
- function getNodeScroll(element) {
1264
- if (isElement(element)) return {
1265
- scrollLeft: element.scrollLeft,
1266
- scrollTop: element.scrollTop
1267
- };
1268
- return {
1269
- scrollLeft: element.scrollX,
1270
- scrollTop: element.scrollY
1271
- };
1272
- }
1273
- function getParentNode(node) {
1274
- if (getNodeName(node) === "html") return node;
1275
- const result = node.assignedSlot || node.parentNode || isShadowRoot(node) && node.host || getDocumentElement(node);
1276
- return isShadowRoot(result) ? result.host : result;
1277
- }
1278
- function getNearestOverflowAncestor(node) {
1279
- const parentNode = getParentNode(node);
1280
- if (isLastTraversableNode(parentNode)) return (node.ownerDocument || node).body;
1281
- if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) return parentNode;
1282
- return getNearestOverflowAncestor(parentNode);
1283
- }
1284
- function getOverflowAncestors(node, list, traverseIframes) {
1285
- var _node$ownerDocument2;
1286
- if (list === void 0) list = [];
1287
- if (traverseIframes === void 0) traverseIframes = true;
1288
- const scrollableAncestor = getNearestOverflowAncestor(node);
1289
- const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
1290
- const win = getWindow(scrollableAncestor);
1291
- if (isBody) {
1292
- const frameElement = getFrameElement(win);
1293
- return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
1294
- } else return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
1295
- }
1296
- function getFrameElement(win) {
1297
- return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
910
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/reason-parts.mjs
911
+ const none = "none";
912
+ const triggerPress = "trigger-press";
913
+ const triggerHover = "trigger-hover";
914
+ const outsidePress = "outside-press";
915
+ const closePress = "close-press";
916
+ const focusOut = "focus-out";
917
+ const escapeKey = "escape-key";
918
+ const disabled = "disabled";
919
+ const missing = "missing";
920
+ const initial = "initial";
921
+ const imperativeAction = "imperative-action";
922
+
923
+ //#endregion
924
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/createBaseUIEventDetails.mjs
925
+ /**
926
+ * Maps a change `reason` string to the corresponding native event type.
927
+ */
928
+ /**
929
+ * Details of custom change events emitted by Base UI components.
930
+ */
931
+ /**
932
+ * Details of custom generic events emitted by Base UI components.
933
+ */
934
+ /**
935
+ * Creates a Base UI event details object with the given reason and utilities
936
+ * for preventing Base UI's internal event handling.
937
+ */
938
+ function createChangeEventDetails(reason, event, trigger, customProperties) {
939
+ let canceled = false;
940
+ let allowPropagation = false;
941
+ const custom = customProperties ?? EMPTY_OBJECT;
942
+ return {
943
+ reason,
944
+ event: event ?? new Event("base-ui"),
945
+ cancel() {
946
+ canceled = true;
947
+ },
948
+ allowPropagation() {
949
+ allowPropagation = true;
950
+ },
951
+ get isCanceled() {
952
+ return canceled;
953
+ },
954
+ get isPropagationAllowed() {
955
+ return allowPropagation;
956
+ },
957
+ trigger,
958
+ ...custom
959
+ };
1298
960
  }
1299
961
 
1300
962
  //#endregion
1301
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useStableCallback.mjs
1302
- const useInsertionEffect = SafeReact.useInsertionEffect;
1303
- const useSafeInsertionEffect = useInsertionEffect && useInsertionEffect !== SafeReact.useLayoutEffect ? useInsertionEffect : (fn) => fn();
1304
- /**
1305
- * Stabilizes the function passed so it's always the same between renders.
1306
- *
1307
- * The function becomes non-reactive to any values it captures.
1308
- * It can safely be passed as a dependency of `React.useMemo` and `React.useEffect` without re-triggering them if its captured values change.
1309
- *
1310
- * The function must only be called inside effects and event handlers, never during render (which throws an error).
1311
- *
1312
- * This hook is a more permissive version of React 19.2's `React.useEffectEvent` in that it can be passed through contexts and called in event handler props, not just effects.
1313
- */
1314
- function useStableCallback(callback) {
1315
- const stable = useRefWithInit(createStableCallback).current;
1316
- stable.next = callback;
1317
- useSafeInsertionEffect(stable.effect);
1318
- return stable.trampoline;
1319
- }
1320
- function createStableCallback() {
1321
- const stable = {
1322
- next: void 0,
1323
- callback: assertNotCalled,
1324
- trampoline: (...args) => stable.callback?.(...args),
1325
- effect: () => {
1326
- stable.callback = stable.next;
1327
- }
1328
- };
1329
- return stable;
1330
- }
1331
- function assertNotCalled() {}
963
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useIsoLayoutEffect.mjs
964
+ const noop = () => {};
965
+ const useIsoLayoutEffect = typeof document !== "undefined" ? react.useLayoutEffect : noop;
1332
966
 
1333
967
  //#endregion
1334
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/composite/root/CompositeRootContext.mjs
1335
- const CompositeRootContext = /* @__PURE__ */ react.createContext(void 0);
1336
- function useCompositeRootContext(optional = false) {
1337
- const context = react.useContext(CompositeRootContext);
1338
- if (context === void 0 && !optional) throw new Error(formatErrorMessage_default(16));
1339
- return context;
968
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useOnMount.mjs
969
+ /**
970
+ * A React.useEffect equivalent that runs once, when the component is mounted.
971
+ */
972
+ function useOnMount(fn) {
973
+ react.useEffect(fn, EMPTY_ARRAY);
1340
974
  }
1341
975
 
1342
976
  //#endregion
1343
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/useFocusableWhenDisabled.mjs
1344
- function useFocusableWhenDisabled(parameters) {
1345
- const { focusableWhenDisabled, disabled: disabled$1, composite = false, tabIndex: tabIndexProp = 0, isNativeButton } = parameters;
1346
- const isFocusableComposite = composite && focusableWhenDisabled !== false;
1347
- const isNonFocusableComposite = composite && focusableWhenDisabled === false;
1348
- return { props: react.useMemo(() => {
1349
- const additionalProps = { onKeyDown(event) {
1350
- if (disabled$1 && focusableWhenDisabled && event.key !== "Tab") event.preventDefault();
1351
- } };
1352
- if (!composite) {
1353
- additionalProps.tabIndex = tabIndexProp;
1354
- if (!isNativeButton && disabled$1) additionalProps.tabIndex = focusableWhenDisabled ? tabIndexProp : -1;
977
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useAnimationFrame.mjs
978
+ /** Unlike `setTimeout`, rAF doesn't guarantee a positive integer return value, so we can't have
979
+ * a monomorphic `uint` type with `0` meaning empty.
980
+ * See warning note at:
981
+ * https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame#return_value */
982
+ const EMPTY$1 = null;
983
+ globalThis.requestAnimationFrame;
984
+ var Scheduler = class {
985
+ callbacks = [];
986
+ callbacksCount = 0;
987
+ nextId = 1;
988
+ startId = 1;
989
+ isScheduled = false;
990
+ tick = (timestamp) => {
991
+ this.isScheduled = false;
992
+ const currentCallbacks = this.callbacks;
993
+ const currentCallbacksCount = this.callbacksCount;
994
+ this.callbacks = [];
995
+ this.callbacksCount = 0;
996
+ this.startId = this.nextId;
997
+ if (currentCallbacksCount > 0) for (let i = 0; i < currentCallbacks.length; i += 1) currentCallbacks[i]?.(timestamp);
998
+ };
999
+ request(fn) {
1000
+ const id = this.nextId;
1001
+ this.nextId += 1;
1002
+ this.callbacks.push(fn);
1003
+ this.callbacksCount += 1;
1004
+ if (!this.isScheduled || false) {
1005
+ requestAnimationFrame(this.tick);
1006
+ this.isScheduled = true;
1355
1007
  }
1356
- if (isNativeButton && (focusableWhenDisabled || isFocusableComposite) || !isNativeButton && disabled$1) additionalProps["aria-disabled"] = disabled$1;
1357
- if (isNativeButton && (!focusableWhenDisabled || isNonFocusableComposite)) additionalProps.disabled = disabled$1;
1358
- return additionalProps;
1359
- }, [
1360
- composite,
1361
- disabled$1,
1362
- focusableWhenDisabled,
1363
- isFocusableComposite,
1364
- isNonFocusableComposite,
1365
- isNativeButton,
1366
- tabIndexProp
1367
- ]) };
1008
+ return id;
1009
+ }
1010
+ cancel(id) {
1011
+ const index$1 = id - this.startId;
1012
+ if (index$1 < 0 || index$1 >= this.callbacks.length) return;
1013
+ this.callbacks[index$1] = null;
1014
+ this.callbacksCount -= 1;
1015
+ }
1016
+ };
1017
+ let scheduler = new Scheduler();
1018
+ var AnimationFrame = class AnimationFrame {
1019
+ static create() {
1020
+ return new AnimationFrame();
1021
+ }
1022
+ static request(fn) {
1023
+ return scheduler.request(fn);
1024
+ }
1025
+ static cancel(id) {
1026
+ return scheduler.cancel(id);
1027
+ }
1028
+ currentId = EMPTY$1;
1029
+ /**
1030
+ * Executes `fn` after `delay`, clearing any previously scheduled call.
1031
+ */
1032
+ request(fn) {
1033
+ this.cancel();
1034
+ this.currentId = scheduler.request(() => {
1035
+ this.currentId = EMPTY$1;
1036
+ fn();
1037
+ });
1038
+ }
1039
+ cancel = () => {
1040
+ if (this.currentId !== EMPTY$1) {
1041
+ scheduler.cancel(this.currentId);
1042
+ this.currentId = EMPTY$1;
1043
+ }
1044
+ };
1045
+ disposeEffect = () => {
1046
+ return this.cancel;
1047
+ };
1048
+ };
1049
+ /**
1050
+ * A `requestAnimationFrame` with automatic cleanup and guard.
1051
+ */
1052
+ function useAnimationFrame() {
1053
+ const timeout = useRefWithInit(AnimationFrame.create).current;
1054
+ useOnMount(timeout.disposeEffect);
1055
+ return timeout;
1368
1056
  }
1369
1057
 
1370
1058
  //#endregion
1371
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/owner.mjs
1372
- function ownerDocument(node) {
1373
- return node?.ownerDocument || document;
1374
- }
1375
-
1376
- //#endregion
1377
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/dispatchClickWithModifiers.mjs
1059
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useTransitionStatus.mjs
1378
1060
  /**
1379
- * Dispatches a constructed click on the target so it carries the source event's
1380
- * modifier state, which `click()` always reports as unpressed. Like `click()`,
1381
- * the untrusted click still runs native activation behavior (form submission,
1382
- * link navigation).
1383
- * `detail` defaults to 0 (the native convention for keyboard-generated clicks);
1384
- * pass `detail: 1` when the click represents a mouse gesture so consumers keying
1385
- * off `detail === 0` don't classify it as a keyboard activation.
1061
+ * Provides a status string for CSS animations.
1062
+ * @param open - a boolean that determines if the element is open.
1063
+ * @param enableIdleState - a boolean that enables the `'idle'` state between `'starting'` and `'ending'`
1386
1064
  */
1387
- function dispatchClickWithModifiers(target, sourceEvent, { detail = 0 } = {}) {
1388
- target.dispatchEvent(new (getWindow(target)).PointerEvent("click", {
1389
- bubbles: true,
1390
- cancelable: true,
1391
- composed: true,
1392
- detail,
1393
- shiftKey: sourceEvent.shiftKey,
1394
- ctrlKey: sourceEvent.ctrlKey,
1395
- altKey: sourceEvent.altKey,
1396
- metaKey: sourceEvent.metaKey
1397
- }));
1065
+ function useTransitionStatus(open, enableIdleState = false, deferEndingState = false) {
1066
+ const [transitionStatus, setTransitionStatus] = react.useState(open && enableIdleState ? "idle" : void 0);
1067
+ const [mounted, setMounted] = react.useState(open);
1068
+ if (open && !mounted) {
1069
+ setMounted(true);
1070
+ setTransitionStatus("starting");
1071
+ }
1072
+ if (!open && mounted && transitionStatus !== "ending" && !deferEndingState) setTransitionStatus("ending");
1073
+ if (!open && !mounted && transitionStatus === "ending") setTransitionStatus(void 0);
1074
+ useIsoLayoutEffect(() => {
1075
+ if (!open && mounted && transitionStatus !== "ending" && deferEndingState) {
1076
+ const frame = AnimationFrame.request(() => {
1077
+ setTransitionStatus("ending");
1078
+ });
1079
+ return () => {
1080
+ AnimationFrame.cancel(frame);
1081
+ };
1082
+ }
1083
+ }, [
1084
+ open,
1085
+ mounted,
1086
+ transitionStatus,
1087
+ deferEndingState
1088
+ ]);
1089
+ useIsoLayoutEffect(() => {
1090
+ if (!open || enableIdleState) return;
1091
+ const frame = AnimationFrame.request(() => {
1092
+ setTransitionStatus(void 0);
1093
+ });
1094
+ return () => {
1095
+ AnimationFrame.cancel(frame);
1096
+ };
1097
+ }, [enableIdleState, open]);
1098
+ useIsoLayoutEffect(() => {
1099
+ if (!open || !enableIdleState) return;
1100
+ if (open && mounted && transitionStatus !== "idle") setTransitionStatus("starting");
1101
+ const frame = AnimationFrame.request(() => {
1102
+ setTransitionStatus("idle");
1103
+ });
1104
+ return () => {
1105
+ AnimationFrame.cancel(frame);
1106
+ };
1107
+ }, [
1108
+ enableIdleState,
1109
+ open,
1110
+ mounted,
1111
+ transitionStatus
1112
+ ]);
1113
+ return {
1114
+ mounted,
1115
+ setMounted,
1116
+ transitionStatus
1117
+ };
1398
1118
  }
1399
1119
 
1400
1120
  //#endregion
1401
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/use-button/useButton.mjs
1402
- function useButton(parameters = {}) {
1403
- const { disabled: disabled$1 = false, focusableWhenDisabled, tabIndex = 0, native: isNativeButton = true, composite: compositeProp } = parameters;
1404
- const elementRef = react.useRef(null);
1405
- const compositeRootContext = useCompositeRootContext(true);
1406
- const isCompositeItem = compositeProp ?? compositeRootContext !== void 0;
1407
- const { props: focusableWhenDisabledProps } = useFocusableWhenDisabled({
1408
- focusableWhenDisabled,
1409
- disabled: disabled$1,
1410
- composite: isCompositeItem,
1411
- tabIndex,
1412
- isNativeButton
1121
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/useCollapsibleRoot.mjs
1122
+ function useCollapsibleRoot(parameters) {
1123
+ const { open: openParam, defaultOpen, onOpenChange, disabled: disabled$1 } = parameters;
1124
+ const [open, setOpen] = useControlled({
1125
+ controlled: openParam,
1126
+ default: defaultOpen,
1127
+ name: "Collapsible",
1128
+ state: "open"
1413
1129
  });
1414
- const updateDisabled = react.useCallback(() => {
1415
- const element = elementRef.current;
1416
- if (!isButtonElement(element)) return;
1417
- if (isCompositeItem && disabled$1 && focusableWhenDisabledProps.disabled === void 0 && element.disabled) element.disabled = false;
1418
- }, [
1130
+ const { mounted, setMounted, transitionStatus } = useTransitionStatus(open, true, true);
1131
+ const defaultPanelId = useBaseUiId();
1132
+ const [registeredPanelId, setPanelIdState] = react.useState();
1133
+ const panelId = registeredPanelId === null ? void 0 : registeredPanelId ?? defaultPanelId;
1134
+ const handleTrigger = useStableCallback((event) => {
1135
+ const nextOpen = !open;
1136
+ const eventDetails = createChangeEventDetails(triggerPress, event.nativeEvent);
1137
+ onOpenChange(nextOpen, eventDetails);
1138
+ if (eventDetails.isCanceled) return;
1139
+ setOpen(nextOpen);
1140
+ });
1141
+ return react.useMemo(() => ({
1142
+ defaultPanelId,
1143
+ disabled: disabled$1,
1144
+ handleTrigger,
1145
+ mounted,
1146
+ open,
1147
+ panelId,
1148
+ setMounted,
1149
+ setOpen,
1150
+ setPanelIdState,
1151
+ transitionStatus
1152
+ }), [
1153
+ defaultPanelId,
1419
1154
  disabled$1,
1420
- focusableWhenDisabledProps.disabled,
1421
- isCompositeItem
1155
+ handleTrigger,
1156
+ mounted,
1157
+ open,
1158
+ panelId,
1159
+ setMounted,
1160
+ setOpen,
1161
+ setPanelIdState,
1162
+ transitionStatus
1422
1163
  ]);
1423
- useIsoLayoutEffect(updateDisabled, [updateDisabled]);
1424
- return {
1425
- getButtonProps: react.useCallback((externalProps = {}) => {
1426
- const { onClick: externalOnClick, onMouseDown: externalOnMouseDown, onKeyUp: externalOnKeyUp, onKeyDown: externalOnKeyDown, onPointerDown: externalOnPointerDown,...otherExternalProps } = externalProps;
1427
- return mergeProps({
1428
- onClick(event) {
1429
- if (disabled$1) {
1430
- event.preventDefault();
1431
- return;
1432
- }
1433
- externalOnClick?.(event);
1434
- },
1435
- onMouseDown(event) {
1436
- if (!disabled$1) externalOnMouseDown?.(event);
1437
- },
1438
- onKeyDown(event) {
1439
- if (disabled$1) return;
1440
- makeEventPreventable(event);
1441
- externalOnKeyDown?.(event);
1442
- if (event.baseUIHandlerPrevented) return;
1443
- const isCurrentTarget = event.target === event.currentTarget;
1444
- const currentTarget = event.currentTarget;
1445
- const isButton = isButtonElement(currentTarget);
1446
- const isLink = !isNativeButton && isValidLinkElement(currentTarget);
1447
- const shouldClick = isCurrentTarget && (isNativeButton ? isButton : !isLink);
1448
- const isEnterKey = event.key === "Enter";
1449
- const isSpaceKey = event.key === " ";
1450
- const role = currentTarget.getAttribute("role");
1451
- const isTextNavigationRole = role?.startsWith("menuitem") || role === "option" || role === "gridcell";
1452
- if (isCurrentTarget && isCompositeItem && isSpaceKey) {
1453
- if (event.defaultPrevented && isTextNavigationRole) return;
1454
- event.preventDefault();
1455
- if (!isNativeButton || isButton) {
1456
- event.preventBaseUIHandler();
1457
- dispatchClickWithModifiers(currentTarget, event);
1458
- }
1459
- return;
1460
- }
1461
- if (!shouldClick || isNativeButton || !isSpaceKey && !isEnterKey) {
1462
- if (isCurrentTarget && isLink && isSpaceKey) event.preventDefault();
1463
- return;
1464
- }
1465
- if (event.defaultPrevented) return;
1466
- event.preventDefault();
1467
- if (isEnterKey) {
1468
- event.preventBaseUIHandler();
1469
- dispatchClickWithModifiers(currentTarget, event);
1470
- }
1471
- },
1472
- onKeyUp(event) {
1473
- if (disabled$1) return;
1474
- makeEventPreventable(event);
1475
- externalOnKeyUp?.(event);
1476
- if (event.target === event.currentTarget && isNativeButton && isCompositeItem && isButtonElement(event.currentTarget) && event.key === " ") {
1477
- event.preventDefault();
1478
- return;
1479
- }
1480
- if (event.baseUIHandlerPrevented) return;
1481
- if (event.target === event.currentTarget && !isNativeButton && !isCompositeItem && !event.defaultPrevented && event.key === " ") {
1482
- event.preventBaseUIHandler();
1483
- dispatchClickWithModifiers(event.currentTarget, event);
1484
- }
1485
- },
1486
- onPointerDown(event) {
1487
- if (disabled$1) {
1488
- event.preventDefault();
1489
- return;
1490
- }
1491
- externalOnPointerDown?.(event);
1492
- }
1493
- }, isNativeButton ? { type: "button" } : { role: "button" }, focusableWhenDisabledProps, otherExternalProps);
1494
- }, [
1495
- disabled$1,
1496
- focusableWhenDisabledProps,
1497
- isCompositeItem,
1498
- isNativeButton
1499
- ]),
1500
- buttonRef: useStableCallback((element) => {
1501
- elementRef.current = element;
1502
- updateDisabled();
1503
- })
1504
- };
1505
- }
1506
- function isButtonElement(elem) {
1507
- return isHTMLElement(elem) && elem.tagName === "BUTTON";
1508
- }
1509
- function isValidLinkElement(elem) {
1510
- return isHTMLElement(elem) && elem.tagName === "A" && Boolean(elem.href);
1511
1164
  }
1512
1165
 
1513
1166
  //#endregion
1514
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/root/SwitchRootContext.mjs
1515
- const SwitchRootContext = /* @__PURE__ */ react.createContext(void 0);
1516
- function useSwitchRootContext() {
1517
- const context = react.useContext(SwitchRootContext);
1518
- if (context === void 0) throw new Error(formatErrorMessage_default(63));
1167
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/CollapsibleRootContext.mjs
1168
+ const CollapsibleRootContext = /* @__PURE__ */ react.createContext(void 0);
1169
+ function useCollapsibleRootContext() {
1170
+ const context = react.useContext(CollapsibleRootContext);
1171
+ if (context === void 0) throw new Error(formatErrorMessage_default(15));
1519
1172
  return context;
1520
1173
  }
1521
1174
 
1522
1175
  //#endregion
1523
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/field-constants/constants.mjs
1524
- const DEFAULT_VALIDITY_STATE = {
1525
- badInput: false,
1526
- customError: false,
1527
- patternMismatch: false,
1528
- rangeOverflow: false,
1529
- rangeUnderflow: false,
1530
- stepMismatch: false,
1531
- tooLong: false,
1532
- tooShort: false,
1533
- typeMismatch: false,
1534
- valid: null,
1535
- valueMissing: false
1536
- };
1537
- const DEFAULT_FIELD_STATE_ATTRIBUTES = {
1538
- valid: null,
1539
- touched: false,
1540
- dirty: false,
1541
- filled: false,
1542
- focused: false
1543
- };
1544
- const DEFAULT_FIELD_ROOT_STATE = {
1545
- disabled: false,
1546
- ...DEFAULT_FIELD_STATE_ATTRIBUTES
1547
- };
1548
- const fieldValidityMapping = { valid(value) {
1549
- if (value === null) return null;
1550
- if (value) return { "data-valid": "" };
1551
- return { "data-invalid": "" };
1176
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/stateAttributesMapping.mjs
1177
+ let TransitionStatusDataAttributes = /* @__PURE__ */ function(TransitionStatusDataAttributes$1) {
1178
+ /**
1179
+ * Present when the component begins animating in.
1180
+ */
1181
+ TransitionStatusDataAttributes$1["startingStyle"] = "data-starting-style";
1182
+ /**
1183
+ * Present when the component is animating out.
1184
+ */
1185
+ TransitionStatusDataAttributes$1["endingStyle"] = "data-ending-style";
1186
+ return TransitionStatusDataAttributes$1;
1187
+ }({});
1188
+ const STARTING_HOOK = { "data-starting-style": "" };
1189
+ const ENDING_HOOK = { "data-ending-style": "" };
1190
+ const transitionStatusMapping = { transitionStatus(value) {
1191
+ if (value === "starting") return STARTING_HOOK;
1192
+ if (value === "ending") return ENDING_HOOK;
1193
+ return null;
1552
1194
  } };
1553
1195
 
1554
1196
  //#endregion
1555
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/stateAttributesMapping.mjs
1556
- const stateAttributesMapping$2 = {
1557
- ...fieldValidityMapping,
1558
- checked(value) {
1559
- if (value) return { "data-checked": "" };
1560
- return { "data-unchecked": "" };
1561
- }
1562
- };
1197
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/CollapsiblePanelDataAttributes.mjs
1198
+ let CollapsiblePanelDataAttributes = function(CollapsiblePanelDataAttributes$1) {
1199
+ /**
1200
+ * Present when the collapsible panel is open.
1201
+ */
1202
+ CollapsiblePanelDataAttributes$1["open"] = "data-open";
1203
+ /**
1204
+ * Present when the collapsible panel is closed.
1205
+ */
1206
+ CollapsiblePanelDataAttributes$1["closed"] = "data-closed";
1207
+ /**
1208
+ * Present when the panel begins animating in.
1209
+ */
1210
+ CollapsiblePanelDataAttributes$1[CollapsiblePanelDataAttributes$1["startingStyle"] = TransitionStatusDataAttributes.startingStyle] = "startingStyle";
1211
+ /**
1212
+ * Present when the panel is animating out.
1213
+ */
1214
+ CollapsiblePanelDataAttributes$1[CollapsiblePanelDataAttributes$1["endingStyle"] = TransitionStatusDataAttributes.endingStyle] = "endingStyle";
1215
+ return CollapsiblePanelDataAttributes$1;
1216
+ }({});
1563
1217
 
1564
1218
  //#endregion
1565
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/field-root-context/FieldRootContext.mjs
1566
- const DEFAULT_FIELD_ROOT_CONTEXT = {
1567
- invalid: void 0,
1568
- name: void 0,
1569
- validityData: {
1570
- state: DEFAULT_VALIDITY_STATE,
1571
- errors: [],
1572
- error: "",
1573
- value: "",
1574
- initialValue: null
1575
- },
1576
- setValidityData: NOOP,
1577
- disabled: void 0,
1578
- setTouched: NOOP,
1579
- setDirty: NOOP,
1580
- setFilled: NOOP,
1581
- setFocused: NOOP,
1582
- validationMode: "onSubmit",
1583
- shouldValidateOnChange: () => false,
1584
- state: DEFAULT_FIELD_ROOT_STATE,
1585
- registerFieldControl: NOOP,
1586
- validation: {
1587
- getValidationProps: (_disabled, props = EMPTY_OBJECT) => props,
1588
- inputRef: { current: null },
1589
- registeredInputs: /* @__PURE__ */ new Map(),
1590
- registerInput: NOOP,
1591
- getInputControl: () => null,
1592
- commit: async () => {},
1593
- change: NOOP
1594
- }
1595
- };
1596
- const FieldRootContext = /* @__PURE__ */ react.createContext(DEFAULT_FIELD_ROOT_CONTEXT);
1597
- function useFieldRootContext(optional = true) {
1598
- const context = react.useContext(FieldRootContext);
1599
- if (context.setValidityData === NOOP && !optional) throw new Error(formatErrorMessage_default(28));
1600
- return context;
1601
- }
1219
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/trigger/CollapsibleTriggerDataAttributes.mjs
1220
+ let CollapsibleTriggerDataAttributes = /* @__PURE__ */ function(CollapsibleTriggerDataAttributes$1) {
1221
+ /**
1222
+ * Present when the collapsible panel is open.
1223
+ */
1224
+ CollapsibleTriggerDataAttributes$1["panelOpen"] = "data-panel-open";
1225
+ return CollapsibleTriggerDataAttributes$1;
1226
+ }({});
1602
1227
 
1603
1228
  //#endregion
1604
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/field-register-control/useRegisterFieldControl.mjs
1605
- function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, enabled = true, name) {
1606
- const { registerFieldControl } = useFieldRootContext();
1607
- const sourceRef = useRefWithInit(() => Symbol());
1608
- useIsoLayoutEffect(() => {
1609
- const source = sourceRef.current;
1610
- if (!enabled) {
1611
- registerFieldControl(source, void 0);
1612
- return;
1613
- }
1614
- registerFieldControl(source, {
1615
- controlRef,
1616
- getValue: getFormValueOverride,
1617
- id,
1618
- name,
1619
- value
1620
- });
1621
- }, [
1622
- controlRef,
1623
- enabled,
1624
- getFormValueOverride,
1625
- id,
1626
- name,
1627
- registerFieldControl,
1628
- sourceRef,
1629
- value
1630
- ]);
1631
- useIsoLayoutEffect(() => {
1632
- const source = sourceRef.current;
1633
- return () => {
1634
- registerFieldControl(source, void 0);
1635
- };
1636
- }, [registerFieldControl, sourceRef]);
1637
- }
1229
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/collapsibleOpenStateMapping.mjs
1230
+ const PANEL_OPEN_HOOK = { [CollapsiblePanelDataAttributes.open]: "" };
1231
+ const PANEL_CLOSED_HOOK = { [CollapsiblePanelDataAttributes.closed]: "" };
1232
+ const triggerOpenStateMapping$1 = { open(value) {
1233
+ if (value) return { [CollapsibleTriggerDataAttributes.panelOpen]: "" };
1234
+ return null;
1235
+ } };
1236
+ const collapsibleOpenStateMapping = { open(value) {
1237
+ if (value) return PANEL_OPEN_HOOK;
1238
+ return PANEL_CLOSED_HOOK;
1239
+ } };
1638
1240
 
1639
1241
  //#endregion
1640
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/form-context/FormContext.mjs
1641
- const FormContext = /* @__PURE__ */ react.createContext({
1642
- elementRef: { current: null },
1643
- formRef: { current: { fields: /* @__PURE__ */ new Map() } },
1644
- errors: {},
1645
- clearErrors: NOOP,
1646
- validationMode: "onSubmit",
1647
- submitAttemptedRef: { current: false }
1648
- });
1649
- function useFormContext() {
1650
- return react.useContext(FormContext);
1651
- }
1242
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/stateAttributesMapping.mjs
1243
+ const collapsibleStateAttributesMapping = {
1244
+ ...collapsibleOpenStateMapping,
1245
+ ...transitionStatusMapping
1246
+ };
1652
1247
 
1653
1248
  //#endregion
1654
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/labelable-provider/LabelableContext.mjs
1249
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/CollapsibleRoot.mjs
1655
1250
  /**
1656
- * A context for providing [labelable elements](https://html.spec.whatwg.org/multipage/forms.html#category-label)\
1657
- * with an accessible name (label) and description.
1251
+ * Groups all parts of the collapsible.
1252
+ * Renders a `<div>` element.
1253
+ *
1254
+ * Documentation: [Base UI Collapsible](https://base-ui.com/react/components/collapsible)
1658
1255
  */
1659
- const LabelableContext = /* @__PURE__ */ react.createContext({
1660
- controlId: void 0,
1661
- registerControlId: NOOP,
1662
- labelId: void 0,
1663
- setLabelId: NOOP,
1664
- messageIds: [],
1665
- setMessageIds: NOOP,
1666
- getDescriptionProps: (externalProps) => externalProps
1256
+ const CollapsibleRoot = /* @__PURE__ */ react.forwardRef(function CollapsibleRoot$1(componentProps, forwardedRef) {
1257
+ const { render, className, defaultOpen = false, disabled: disabled$1 = false, onOpenChange: onOpenChangeProp, open, style,...elementProps } = componentProps;
1258
+ const onOpenChange = useStableCallback(onOpenChangeProp);
1259
+ const collapsible = useCollapsibleRoot({
1260
+ open,
1261
+ defaultOpen,
1262
+ onOpenChange,
1263
+ disabled: disabled$1
1264
+ });
1265
+ const state = react.useMemo(() => ({
1266
+ open: collapsible.open,
1267
+ disabled: collapsible.disabled,
1268
+ transitionStatus: collapsible.transitionStatus
1269
+ }), [
1270
+ collapsible.open,
1271
+ collapsible.disabled,
1272
+ collapsible.transitionStatus
1273
+ ]);
1274
+ const contextValue = react.useMemo(() => ({
1275
+ ...collapsible,
1276
+ onOpenChange,
1277
+ state
1278
+ }), [
1279
+ collapsible,
1280
+ onOpenChange,
1281
+ state
1282
+ ]);
1283
+ const element = useRenderElement("div", componentProps, {
1284
+ state,
1285
+ ref: forwardedRef,
1286
+ props: elementProps,
1287
+ stateAttributesMapping: collapsibleStateAttributesMapping
1288
+ });
1289
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleRootContext.Provider, {
1290
+ value: contextValue,
1291
+ children: element
1292
+ });
1667
1293
  });
1668
- function useLabelableContext() {
1669
- return react.useContext(LabelableContext);
1670
- }
1671
1294
 
1672
1295
  //#endregion
1673
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/labelable-provider/useAriaLabelledBy.mjs
1674
- function useAriaLabelledBy(explicitAriaLabelledBy, labelId, labelSourceRef, enableFallback = true, labelSourceId) {
1675
- const [fallbackAriaLabelledBy, setFallbackAriaLabelledBy] = react.useState();
1676
- const generatedLabelId = useBaseUiId(labelSourceId ? `${labelSourceId}-label` : void 0);
1677
- const ariaLabelledBy = explicitAriaLabelledBy ?? labelId ?? fallbackAriaLabelledBy;
1678
- useIsoLayoutEffect(() => {
1679
- const nextAriaLabelledBy = explicitAriaLabelledBy || labelId || !enableFallback ? void 0 : getAriaLabelledBy(labelSourceRef.current, generatedLabelId);
1680
- if (fallbackAriaLabelledBy !== nextAriaLabelledBy) setFallbackAriaLabelledBy(nextAriaLabelledBy);
1681
- });
1682
- return ariaLabelledBy;
1296
+ //#region node_modules/.pnpm/@floating-ui+utils@0.2.12/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs
1297
+ function hasWindow() {
1298
+ return typeof window !== "undefined";
1683
1299
  }
1684
- function getAriaLabelledBy(labelSource, generatedLabelId) {
1685
- const label = findAssociatedLabel(labelSource);
1686
- if (!label) return;
1687
- if (!label.id && generatedLabelId) label.id = generatedLabelId;
1688
- return label.id || void 0;
1300
+ function getNodeName(node) {
1301
+ if (isNode(node)) return (node.nodeName || "").toLowerCase();
1302
+ return "#document";
1689
1303
  }
1690
- function findAssociatedLabel(labelSource) {
1691
- if (!labelSource) return;
1692
- const parent = labelSource.parentElement;
1693
- if (parent && parent.tagName === "LABEL") return parent;
1694
- const controlId = labelSource.id;
1695
- if (controlId) {
1696
- const nextSibling = labelSource.nextElementSibling;
1697
- if (nextSibling && nextSibling.htmlFor === controlId) return nextSibling;
1698
- }
1699
- const labels = labelSource.labels;
1700
- return labels && labels[0];
1304
+ function getWindow(node) {
1305
+ var _node$ownerDocument;
1306
+ return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
1701
1307
  }
1702
-
1308
+ function getDocumentElement(node) {
1309
+ var _ref;
1310
+ return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
1311
+ }
1312
+ function isNode(value) {
1313
+ if (!hasWindow()) return false;
1314
+ return value instanceof Node || value instanceof getWindow(value).Node;
1315
+ }
1316
+ function isElement(value) {
1317
+ if (!hasWindow()) return false;
1318
+ return value instanceof Element || value instanceof getWindow(value).Element;
1319
+ }
1320
+ function isHTMLElement(value) {
1321
+ if (!hasWindow()) return false;
1322
+ return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
1323
+ }
1324
+ function isShadowRoot(value) {
1325
+ if (!hasWindow() || typeof ShadowRoot === "undefined") return false;
1326
+ return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
1327
+ }
1328
+ function isOverflowElement(element) {
1329
+ const { overflow, overflowX, overflowY, display } = getComputedStyle$1(element);
1330
+ return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== "inline" && display !== "contents";
1331
+ }
1332
+ function isTableElement(element) {
1333
+ return /^(table|td|th)$/.test(getNodeName(element));
1334
+ }
1335
+ function isTopLayer(element) {
1336
+ try {
1337
+ if (element.matches(":popover-open")) return true;
1338
+ } catch (_e) {}
1339
+ try {
1340
+ return element.matches(":modal");
1341
+ } catch (_e) {
1342
+ return false;
1343
+ }
1344
+ }
1345
+ const willChangeRe = /transform|translate|scale|rotate|perspective|filter/;
1346
+ const containRe = /paint|layout|strict|content/;
1347
+ const isNotNone = (value) => !!value && value !== "none";
1348
+ let isWebKitValue;
1349
+ function isContainingBlock(elementOrCss) {
1350
+ const css = isElement(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss;
1351
+ return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || "") || containRe.test(css.contain || "");
1352
+ }
1353
+ function getContainingBlock(element) {
1354
+ let currentNode = getParentNode(element);
1355
+ while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
1356
+ if (isContainingBlock(currentNode)) return currentNode;
1357
+ else if (isTopLayer(currentNode)) return null;
1358
+ currentNode = getParentNode(currentNode);
1359
+ }
1360
+ return null;
1361
+ }
1362
+ function isWebKit() {
1363
+ if (isWebKitValue == null) isWebKitValue = typeof CSS !== "undefined" && CSS.supports && CSS.supports("-webkit-backdrop-filter", "none");
1364
+ return isWebKitValue;
1365
+ }
1366
+ function isLastTraversableNode(node) {
1367
+ return /^(html|body|#document)$/.test(getNodeName(node));
1368
+ }
1369
+ function getComputedStyle$1(element) {
1370
+ return getWindow(element).getComputedStyle(element);
1371
+ }
1372
+ function getNodeScroll(element) {
1373
+ if (isElement(element)) return {
1374
+ scrollLeft: element.scrollLeft,
1375
+ scrollTop: element.scrollTop
1376
+ };
1377
+ return {
1378
+ scrollLeft: element.scrollX,
1379
+ scrollTop: element.scrollY
1380
+ };
1381
+ }
1382
+ function getParentNode(node) {
1383
+ if (getNodeName(node) === "html") return node;
1384
+ const result = node.assignedSlot || node.parentNode || isShadowRoot(node) && node.host || getDocumentElement(node);
1385
+ return isShadowRoot(result) ? result.host : result;
1386
+ }
1387
+ function getNearestOverflowAncestor(node) {
1388
+ const parentNode = getParentNode(node);
1389
+ if (isLastTraversableNode(parentNode)) return (node.ownerDocument || node).body;
1390
+ if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) return parentNode;
1391
+ return getNearestOverflowAncestor(parentNode);
1392
+ }
1393
+ function getOverflowAncestors(node, list, traverseIframes) {
1394
+ var _node$ownerDocument2;
1395
+ if (list === void 0) list = [];
1396
+ if (traverseIframes === void 0) traverseIframes = true;
1397
+ const scrollableAncestor = getNearestOverflowAncestor(node);
1398
+ const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
1399
+ const win = getWindow(scrollableAncestor);
1400
+ if (isBody) {
1401
+ const frameElement = getFrameElement(win);
1402
+ return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
1403
+ } else return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
1404
+ }
1405
+ function getFrameElement(win) {
1406
+ return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
1407
+ }
1408
+
1703
1409
  //#endregion
1704
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/labelable-provider/useLabelableId.mjs
1705
- function useLabelableId(params = {}) {
1706
- const { id, implicit = false, controlRef } = params;
1707
- const { controlId, registerControlId } = useLabelableContext();
1708
- const defaultId = useBaseUiId(id);
1709
- const controlIdForEffect = implicit ? controlId : void 0;
1710
- const controlSourceRef = useRefWithInit(() => Symbol());
1711
- const hasRegisteredRef = react.useRef(false);
1712
- const hadExplicitIdRef = react.useRef(id != null);
1713
- const unregisterControlId = useStableCallback(() => {
1714
- if (!hasRegisteredRef.current || registerControlId === NOOP) return;
1715
- hasRegisteredRef.current = false;
1716
- registerControlId(controlSourceRef.current, void 0);
1717
- });
1718
- useIsoLayoutEffect(() => {
1719
- if (registerControlId === NOOP) return;
1720
- let nextId;
1721
- if (implicit) {
1722
- const elem = controlRef?.current;
1723
- if (isElement(elem) && elem.closest("label") != null) nextId = id ?? null;
1724
- else nextId = controlIdForEffect ?? defaultId;
1725
- } else if (id != null) {
1726
- hadExplicitIdRef.current = true;
1727
- nextId = id;
1728
- } else if (hadExplicitIdRef.current) nextId = defaultId;
1729
- else {
1730
- unregisterControlId();
1731
- return;
1732
- }
1733
- if (nextId === void 0) {
1734
- unregisterControlId();
1735
- return;
1410
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/composite/root/CompositeRootContext.mjs
1411
+ const CompositeRootContext = /* @__PURE__ */ react.createContext(void 0);
1412
+ function useCompositeRootContext(optional = false) {
1413
+ const context = react.useContext(CompositeRootContext);
1414
+ if (context === void 0 && !optional) throw new Error(formatErrorMessage_default(16));
1415
+ return context;
1416
+ }
1417
+
1418
+ //#endregion
1419
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/useFocusableWhenDisabled.mjs
1420
+ function useFocusableWhenDisabled(parameters) {
1421
+ const { focusableWhenDisabled, disabled: disabled$1, composite = false, tabIndex: tabIndexProp = 0, isNativeButton } = parameters;
1422
+ const isFocusableComposite = composite && focusableWhenDisabled !== false;
1423
+ const isNonFocusableComposite = composite && focusableWhenDisabled === false;
1424
+ return { props: react.useMemo(() => {
1425
+ const additionalProps = { onKeyDown(event) {
1426
+ if (disabled$1 && focusableWhenDisabled && event.key !== "Tab") event.preventDefault();
1427
+ } };
1428
+ if (!composite) {
1429
+ additionalProps.tabIndex = tabIndexProp;
1430
+ if (!isNativeButton && disabled$1) additionalProps.tabIndex = focusableWhenDisabled ? tabIndexProp : -1;
1736
1431
  }
1737
- hasRegisteredRef.current = true;
1738
- registerControlId(controlSourceRef.current, nextId);
1432
+ if (isNativeButton && (focusableWhenDisabled || isFocusableComposite) || !isNativeButton && disabled$1) additionalProps["aria-disabled"] = disabled$1;
1433
+ if (isNativeButton && (!focusableWhenDisabled || isNonFocusableComposite)) additionalProps.disabled = disabled$1;
1434
+ return additionalProps;
1739
1435
  }, [
1740
- id,
1741
- controlRef,
1742
- controlIdForEffect,
1743
- registerControlId,
1744
- implicit,
1745
- defaultId,
1746
- controlSourceRef,
1747
- unregisterControlId
1748
- ]);
1749
- react.useEffect(() => {
1750
- return unregisterControlId;
1751
- }, [unregisterControlId]);
1752
- return controlId ?? defaultId;
1436
+ composite,
1437
+ disabled$1,
1438
+ focusableWhenDisabled,
1439
+ isFocusableComposite,
1440
+ isNonFocusableComposite,
1441
+ isNativeButton,
1442
+ tabIndexProp
1443
+ ]) };
1753
1444
  }
1754
1445
 
1755
1446
  //#endregion
1756
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/reason-parts.mjs
1757
- const none = "none";
1758
- const triggerPress = "trigger-press";
1759
- const triggerHover = "trigger-hover";
1760
- const outsidePress = "outside-press";
1761
- const closePress = "close-press";
1762
- const focusOut = "focus-out";
1763
- const escapeKey = "escape-key";
1764
- const disabled = "disabled";
1765
- const missing = "missing";
1766
- const initial = "initial";
1767
- const imperativeAction = "imperative-action";
1447
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/owner.mjs
1448
+ function ownerDocument(node) {
1449
+ return node?.ownerDocument || document;
1450
+ }
1768
1451
 
1769
1452
  //#endregion
1770
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/createBaseUIEventDetails.mjs
1771
- /**
1772
- * Maps a change `reason` string to the corresponding native event type.
1773
- */
1774
- /**
1775
- * Details of custom change events emitted by Base UI components.
1776
- */
1777
- /**
1778
- * Details of custom generic events emitted by Base UI components.
1779
- */
1453
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/dispatchClickWithModifiers.mjs
1780
1454
  /**
1781
- * Creates a Base UI event details object with the given reason and utilities
1782
- * for preventing Base UI's internal event handling.
1455
+ * Dispatches a constructed click on the target so it carries the source event's
1456
+ * modifier state, which `click()` always reports as unpressed. Like `click()`,
1457
+ * the untrusted click still runs native activation behavior (form submission,
1458
+ * link navigation).
1459
+ * `detail` defaults to 0 (the native convention for keyboard-generated clicks);
1460
+ * pass `detail: 1` when the click represents a mouse gesture so consumers keying
1461
+ * off `detail === 0` don't classify it as a keyboard activation.
1783
1462
  */
1784
- function createChangeEventDetails(reason, event, trigger, customProperties) {
1785
- let canceled = false;
1786
- let allowPropagation = false;
1787
- const custom = customProperties ?? EMPTY_OBJECT;
1788
- return {
1789
- reason,
1790
- event: event ?? new Event("base-ui"),
1791
- cancel() {
1792
- canceled = true;
1793
- },
1794
- allowPropagation() {
1795
- allowPropagation = true;
1796
- },
1797
- get isCanceled() {
1798
- return canceled;
1799
- },
1800
- get isPropagationAllowed() {
1801
- return allowPropagation;
1802
- },
1803
- trigger,
1804
- ...custom
1805
- };
1463
+ function dispatchClickWithModifiers(target, sourceEvent, { detail = 0 } = {}) {
1464
+ target.dispatchEvent(new (getWindow(target)).PointerEvent("click", {
1465
+ bubbles: true,
1466
+ cancelable: true,
1467
+ composed: true,
1468
+ detail,
1469
+ shiftKey: sourceEvent.shiftKey,
1470
+ ctrlKey: sourceEvent.ctrlKey,
1471
+ altKey: sourceEvent.altKey,
1472
+ metaKey: sourceEvent.metaKey
1473
+ }));
1806
1474
  }
1807
1475
 
1808
1476
  //#endregion
1809
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useValueChanged.mjs
1810
- function useValueChanged(value, onChange) {
1811
- const valueRef = react.useRef(value);
1812
- const onChangeCallback = useStableCallback(onChange);
1813
- useIsoLayoutEffect(() => {
1814
- if (valueRef.current !== value) onChangeCallback(valueRef.current);
1815
- valueRef.current = value;
1816
- }, [value, onChangeCallback]);
1477
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/use-button/useButton.mjs
1478
+ function useButton(parameters = {}) {
1479
+ const { disabled: disabled$1 = false, focusableWhenDisabled, tabIndex = 0, native: isNativeButton = true, composite: compositeProp } = parameters;
1480
+ const elementRef = react.useRef(null);
1481
+ const compositeRootContext = useCompositeRootContext(true);
1482
+ const isCompositeItem = compositeProp ?? compositeRootContext !== void 0;
1483
+ const { props: focusableWhenDisabledProps } = useFocusableWhenDisabled({
1484
+ focusableWhenDisabled,
1485
+ disabled: disabled$1,
1486
+ composite: isCompositeItem,
1487
+ tabIndex,
1488
+ isNativeButton
1489
+ });
1490
+ const updateDisabled = react.useCallback(() => {
1491
+ const element = elementRef.current;
1492
+ if (!isButtonElement(element)) return;
1493
+ if (isCompositeItem && disabled$1 && focusableWhenDisabledProps.disabled === void 0 && element.disabled) element.disabled = false;
1494
+ }, [
1495
+ disabled$1,
1496
+ focusableWhenDisabledProps.disabled,
1497
+ isCompositeItem
1498
+ ]);
1499
+ useIsoLayoutEffect(updateDisabled, [updateDisabled]);
1500
+ return {
1501
+ getButtonProps: react.useCallback((externalProps = {}) => {
1502
+ const { onClick: externalOnClick, onMouseDown: externalOnMouseDown, onKeyUp: externalOnKeyUp, onKeyDown: externalOnKeyDown, onPointerDown: externalOnPointerDown,...otherExternalProps } = externalProps;
1503
+ return mergeProps({
1504
+ onClick(event) {
1505
+ if (disabled$1) {
1506
+ event.preventDefault();
1507
+ return;
1508
+ }
1509
+ externalOnClick?.(event);
1510
+ },
1511
+ onMouseDown(event) {
1512
+ if (!disabled$1) externalOnMouseDown?.(event);
1513
+ },
1514
+ onKeyDown(event) {
1515
+ if (disabled$1) return;
1516
+ makeEventPreventable(event);
1517
+ externalOnKeyDown?.(event);
1518
+ if (event.baseUIHandlerPrevented) return;
1519
+ const isCurrentTarget = event.target === event.currentTarget;
1520
+ const currentTarget = event.currentTarget;
1521
+ const isButton = isButtonElement(currentTarget);
1522
+ const isLink = !isNativeButton && isValidLinkElement(currentTarget);
1523
+ const shouldClick = isCurrentTarget && (isNativeButton ? isButton : !isLink);
1524
+ const isEnterKey = event.key === "Enter";
1525
+ const isSpaceKey = event.key === " ";
1526
+ const role = currentTarget.getAttribute("role");
1527
+ const isTextNavigationRole = role?.startsWith("menuitem") || role === "option" || role === "gridcell";
1528
+ if (isCurrentTarget && isCompositeItem && isSpaceKey) {
1529
+ if (event.defaultPrevented && isTextNavigationRole) return;
1530
+ event.preventDefault();
1531
+ if (!isNativeButton || isButton) {
1532
+ event.preventBaseUIHandler();
1533
+ dispatchClickWithModifiers(currentTarget, event);
1534
+ }
1535
+ return;
1536
+ }
1537
+ if (!shouldClick || isNativeButton || !isSpaceKey && !isEnterKey) {
1538
+ if (isCurrentTarget && isLink && isSpaceKey) event.preventDefault();
1539
+ return;
1540
+ }
1541
+ if (event.defaultPrevented) return;
1542
+ event.preventDefault();
1543
+ if (isEnterKey) {
1544
+ event.preventBaseUIHandler();
1545
+ dispatchClickWithModifiers(currentTarget, event);
1546
+ }
1547
+ },
1548
+ onKeyUp(event) {
1549
+ if (disabled$1) return;
1550
+ makeEventPreventable(event);
1551
+ externalOnKeyUp?.(event);
1552
+ if (event.target === event.currentTarget && isNativeButton && isCompositeItem && isButtonElement(event.currentTarget) && event.key === " ") {
1553
+ event.preventDefault();
1554
+ return;
1555
+ }
1556
+ if (event.baseUIHandlerPrevented) return;
1557
+ if (event.target === event.currentTarget && !isNativeButton && !isCompositeItem && !event.defaultPrevented && event.key === " ") {
1558
+ event.preventBaseUIHandler();
1559
+ dispatchClickWithModifiers(event.currentTarget, event);
1560
+ }
1561
+ },
1562
+ onPointerDown(event) {
1563
+ if (disabled$1) {
1564
+ event.preventDefault();
1565
+ return;
1566
+ }
1567
+ externalOnPointerDown?.(event);
1568
+ }
1569
+ }, isNativeButton ? { type: "button" } : { role: "button" }, focusableWhenDisabledProps, otherExternalProps);
1570
+ }, [
1571
+ disabled$1,
1572
+ focusableWhenDisabledProps,
1573
+ isCompositeItem,
1574
+ isNativeButton
1575
+ ]),
1576
+ buttonRef: useStableCallback((element) => {
1577
+ elementRef.current = element;
1578
+ updateDisabled();
1579
+ })
1580
+ };
1581
+ }
1582
+ function isButtonElement(elem) {
1583
+ return isHTMLElement(elem) && elem.tagName === "BUTTON";
1584
+ }
1585
+ function isValidLinkElement(elem) {
1586
+ return isHTMLElement(elem) && elem.tagName === "A" && Boolean(elem.href);
1817
1587
  }
1818
1588
 
1819
1589
  //#endregion
1820
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/root/SwitchRoot.mjs
1821
- const SwitchRoot = /* @__PURE__ */ react.forwardRef(function SwitchRoot$1(componentProps, forwardedRef) {
1822
- const { checked: checkedProp, className, defaultChecked, "aria-labelledby": ariaLabelledByProp, form, id: idProp, inputRef: externalInputRef, name: nameProp, nativeButton = false, onCheckedChange, readOnly = false, required = false, disabled: disabledProp = false, render, uncheckedValue, value, style,...elementProps } = componentProps;
1823
- const { clearErrors } = useFormContext();
1824
- const { state: fieldState, setTouched, setDirty, validityData, setFilled, setFocused, validationMode, disabled: fieldDisabled, name: fieldName, validation } = useFieldRootContext();
1825
- const { labelId } = useLabelableContext();
1826
- const disabled$1 = fieldDisabled || disabledProp;
1827
- const name = fieldName ?? nameProp;
1828
- const inputRef = react.useRef(null);
1829
- const handleInputRef = useMergedRefs(inputRef, externalInputRef, validation.inputRef);
1830
- const switchRef = react.useRef(null);
1831
- const id = useBaseUiId();
1832
- const controlId = useLabelableId({
1833
- id: idProp,
1834
- implicit: false,
1835
- controlRef: switchRef
1836
- });
1837
- const hiddenInputId = nativeButton ? void 0 : controlId;
1838
- const [checked, setCheckedState] = useControlled({
1839
- controlled: checkedProp,
1840
- default: Boolean(defaultChecked),
1841
- name: "Switch",
1842
- state: "checked"
1843
- });
1844
- useRegisterFieldControl(switchRef, id, checked, void 0, !disabled$1, nameProp);
1845
- useIsoLayoutEffect(() => {
1846
- if (inputRef.current) setFilled(inputRef.current.checked);
1847
- }, [setFilled]);
1848
- useValueChanged(checked, () => {
1849
- clearErrors(name);
1850
- setDirty(checked !== validityData.initialValue);
1851
- setFilled(checked);
1852
- validation.change(checked);
1853
- });
1590
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/trigger/CollapsibleTrigger.mjs
1591
+ const stateAttributesMapping$2 = {
1592
+ ...triggerOpenStateMapping$1,
1593
+ ...transitionStatusMapping
1594
+ };
1595
+ /**
1596
+ * A button that opens and closes the collapsible panel.
1597
+ * Renders a `<button>` element.
1598
+ *
1599
+ * Documentation: [Base UI Collapsible](https://base-ui.com/react/components/collapsible)
1600
+ */
1601
+ const CollapsibleTrigger = /* @__PURE__ */ react.forwardRef(function CollapsibleTrigger$1(componentProps, forwardedRef) {
1602
+ const { panelId, open, handleTrigger, state, disabled: contextDisabled } = useCollapsibleRootContext();
1603
+ const { className, disabled: disabled$1 = contextDisabled, render, nativeButton = true, style,...elementProps } = componentProps;
1854
1604
  const { getButtonProps, buttonRef } = useButton({
1855
1605
  disabled: disabled$1,
1606
+ focusableWhenDisabled: true,
1856
1607
  native: nativeButton
1857
1608
  });
1858
- const ariaLabelledBy = useAriaLabelledBy(ariaLabelledByProp, labelId, inputRef, !nativeButton, hiddenInputId);
1859
- const rootProps = {
1860
- id: nativeButton ? controlId : id,
1861
- role: "switch",
1862
- "aria-checked": checked,
1863
- "aria-readonly": readOnly || void 0,
1864
- "aria-required": required || void 0,
1865
- "aria-labelledby": ariaLabelledBy,
1866
- onFocus() {
1867
- if (!disabled$1) setFocused(true);
1868
- },
1869
- onBlur() {
1870
- const element$1 = inputRef.current;
1871
- if (!element$1 || disabled$1) return;
1872
- setTouched(true);
1873
- setFocused(false);
1874
- if (validationMode === "onBlur") validation.commit(element$1.checked);
1875
- },
1876
- onClick(event) {
1877
- if (readOnly || disabled$1) return;
1878
- event.preventDefault();
1879
- const input = inputRef.current;
1880
- if (!input) return;
1881
- dispatchClickWithModifiers(input, event);
1882
- }
1883
- };
1884
- const inputProps = {
1885
- ...validation.getValidationProps(disabled$1),
1886
- checked,
1887
- disabled: disabled$1,
1888
- form,
1889
- id: hiddenInputId,
1890
- name,
1891
- required,
1892
- style: name ? visuallyHiddenInput : visuallyHidden,
1893
- tabIndex: -1,
1894
- type: "checkbox",
1895
- "aria-hidden": true,
1896
- ref: handleInputRef,
1897
- onChange(event) {
1898
- if (event.nativeEvent.defaultPrevented) return;
1899
- if (readOnly) {
1900
- event.preventDefault();
1901
- return;
1902
- }
1903
- const nextChecked = event.currentTarget.checked;
1904
- const eventDetails = createChangeEventDetails(none, event.nativeEvent);
1905
- onCheckedChange?.(nextChecked, eventDetails);
1906
- if (eventDetails.isCanceled) return;
1907
- setCheckedState(nextChecked);
1908
- },
1909
- onClick(event) {
1910
- event.stopPropagation();
1911
- },
1912
- onFocus() {
1913
- switchRef.current?.focus();
1914
- },
1915
- ...value !== void 0 ? { value } : EMPTY_OBJECT
1916
- };
1917
- const state = react.useMemo(() => ({
1918
- ...fieldState,
1919
- checked,
1920
- disabled: disabled$1,
1921
- readOnly,
1922
- required
1923
- }), [
1924
- fieldState,
1925
- checked,
1926
- disabled$1,
1927
- readOnly,
1928
- required
1929
- ]);
1930
- const element = useRenderElement("span", componentProps, {
1609
+ return useRenderElement("button", componentProps, {
1931
1610
  state,
1932
- ref: [
1933
- forwardedRef,
1934
- switchRef,
1935
- buttonRef
1936
- ],
1611
+ ref: [forwardedRef, buttonRef],
1937
1612
  props: [
1938
- rootProps,
1613
+ {
1614
+ "aria-controls": open ? panelId : void 0,
1615
+ "aria-expanded": open,
1616
+ onClick: handleTrigger
1617
+ },
1939
1618
  elementProps,
1940
- getButtonProps,
1941
- (props) => validation.getValidationProps(disabled$1, props)
1619
+ getButtonProps
1942
1620
  ],
1943
1621
  stateAttributesMapping: stateAttributesMapping$2
1944
1622
  });
1945
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SwitchRootContext.Provider, {
1946
- value: state,
1947
- children: [
1948
- element,
1949
- !checked && name && uncheckedValue !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1950
- type: "hidden",
1951
- form,
1952
- name,
1953
- value: uncheckedValue,
1954
- disabled: disabled$1
1955
- }),
1956
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1957
- ...inputProps,
1958
- suppressHydrationWarning: true
1959
- })
1960
- ]
1961
- });
1962
1623
  });
1963
1624
 
1964
1625
  //#endregion
1965
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/thumb/SwitchThumb.mjs
1626
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/addEventListener.mjs
1966
1627
  /**
1967
- * The movable part of the switch that indicates whether the switch is on or off.
1968
- * Renders a `<span>`.
1969
- *
1970
- * Documentation: [Base UI Switch](https://base-ui.com/react/components/switch)
1628
+ * Adds an event listener and returns a cleanup function to remove it.
1971
1629
  */
1972
- const SwitchThumb = /* @__PURE__ */ react.forwardRef(function SwitchThumb$1(componentProps, forwardedRef) {
1973
- const { render, className, style,...elementProps } = componentProps;
1974
- return useRenderElement("span", componentProps, {
1975
- state: useSwitchRootContext(),
1976
- ref: forwardedRef,
1977
- stateAttributesMapping: stateAttributesMapping$2,
1978
- props: elementProps
1979
- });
1980
- });
1630
+ function addEventListener(target, type, listener, options) {
1631
+ target.addEventListener(type, listener, options);
1632
+ return () => {
1633
+ target.removeEventListener(type, listener, options);
1634
+ };
1635
+ }
1981
1636
 
1982
1637
  //#endregion
1983
- //#region src/client/switch.ts
1638
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useValueAsRef.mjs
1984
1639
  /**
1985
- * The capability switch, in one place for both panels.
1640
+ * Untracks the provided value by turning it into a ref to remove its reactivity.
1986
1641
  *
1987
- * dsh 0.1.7 ships a design-system `Switch` (36×20 capsule, brand-primary on
1988
- * state, its own disabled dimming and focus ring) — using it keeps the panel's
1989
- * toggles pixel-identical to every settings page the host ships, which is the
1990
- * alignment this file exists for. Hosts older than that export fall back to
1991
- * the local Base UI rendition below, so one build still serves both
1992
- * generations; the probe runs per call, the same way the icon table resolves.
1642
+ * Used to access the passed value inside `React.useEffect` without causing the effect to re-run when the value changes.
1993
1643
  */
1994
- function capabilitySwitch(options) {
1995
- const inert = options.disabled || options.busy;
1996
- const HostSwitch = __deepseek_ai_dsh_client_ui_primitives.Switch;
1997
- if (HostSwitch !== void 0) return react.createElement(HostSwitch, {
1998
- checked: options.checked,
1999
- onChange: options.onCheckedChange,
2000
- label: options.label,
2001
- disabled: inert
2002
- });
2003
- return react.createElement(SwitchRoot, {
2004
- className: "ci-switch",
2005
- checked: options.checked,
2006
- disabled: inert,
2007
- "aria-label": options.label,
2008
- onCheckedChange: options.onCheckedChange,
2009
- style: {
2010
- position: "relative",
2011
- width: "32px",
2012
- height: "18px",
2013
- padding: 0,
2014
- border: "none",
2015
- borderRadius: "999px",
2016
- background: options.checked ? TOK.switchOn : TOK.switchOff,
2017
- cursor: inert ? "not-allowed" : "pointer",
2018
- opacity: options.busy ? .65 : 1,
2019
- flex: "0 0 auto"
2020
- }
2021
- }, react.createElement(SwitchThumb, {
2022
- className: "ci-thumb",
2023
- style: {
2024
- display: "block",
2025
- width: "14px",
2026
- height: "14px",
2027
- margin: "2px",
2028
- borderRadius: "999px",
2029
- background: TOK.switchThumb,
2030
- boxShadow: "0 1px 2px rgba(0,0,0,.22)",
2031
- transform: options.checked ? "translateX(14px)" : "translateX(0)",
2032
- transition: `transform .12s ${TOK.switchEase}`
1644
+ function useValueAsRef(value) {
1645
+ const latest = useRefWithInit(createLatestRef, value).current;
1646
+ latest.next = value;
1647
+ useIsoLayoutEffect(latest.effect);
1648
+ return latest;
1649
+ }
1650
+ function createLatestRef(value) {
1651
+ const latest = {
1652
+ current: value,
1653
+ next: value,
1654
+ effect: () => {
1655
+ latest.current = latest.next;
2033
1656
  }
2034
- }));
1657
+ };
1658
+ return latest;
2035
1659
  }
2036
1660
 
2037
1661
  //#endregion
2038
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useOnMount.mjs
1662
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/resolveRef.mjs
2039
1663
  /**
2040
- * A React.useEffect equivalent that runs once, when the component is mounted.
1664
+ * If the provided argument is a ref object, returns its `current` value.
1665
+ * Otherwise, returns the argument itself.
2041
1666
  */
2042
- function useOnMount(fn) {
2043
- react.useEffect(fn, EMPTY_ARRAY);
1667
+ function resolveRef(maybeRef) {
1668
+ if (maybeRef == null) return maybeRef;
1669
+ return "current" in maybeRef ? maybeRef.current : maybeRef;
2044
1670
  }
2045
1671
 
2046
1672
  //#endregion
2047
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useAnimationFrame.mjs
2048
- /** Unlike `setTimeout`, rAF doesn't guarantee a positive integer return value, so we can't have
2049
- * a monomorphic `uint` type with `0` meaning empty.
2050
- * See warning note at:
2051
- * https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame#return_value */
2052
- const EMPTY$1 = null;
2053
- globalThis.requestAnimationFrame;
2054
- var Scheduler = class {
2055
- callbacks = [];
2056
- callbacksCount = 0;
2057
- nextId = 1;
2058
- startId = 1;
2059
- isScheduled = false;
2060
- tick = (timestamp) => {
2061
- this.isScheduled = false;
2062
- const currentCallbacks = this.callbacks;
2063
- const currentCallbacksCount = this.callbacksCount;
2064
- this.callbacks = [];
2065
- this.callbacksCount = 0;
2066
- this.startId = this.nextId;
2067
- if (currentCallbacksCount > 0) for (let i = 0; i < currentCallbacks.length; i += 1) currentCallbacks[i]?.(timestamp);
2068
- };
2069
- request(fn) {
2070
- const id = this.nextId;
2071
- this.nextId += 1;
2072
- this.callbacks.push(fn);
2073
- this.callbacksCount += 1;
2074
- if (!this.isScheduled || false) {
2075
- requestAnimationFrame(this.tick);
2076
- this.isScheduled = true;
2077
- }
2078
- return id;
2079
- }
2080
- cancel(id) {
2081
- const index$1 = id - this.startId;
2082
- if (index$1 < 0 || index$1 >= this.callbacks.length) return;
2083
- this.callbacks[index$1] = null;
2084
- this.callbacksCount -= 1;
2085
- }
2086
- };
2087
- let scheduler = new Scheduler();
2088
- var AnimationFrame = class AnimationFrame {
2089
- static create() {
2090
- return new AnimationFrame();
2091
- }
2092
- static request(fn) {
2093
- return scheduler.request(fn);
2094
- }
2095
- static cancel(id) {
2096
- return scheduler.cancel(id);
2097
- }
2098
- currentId = EMPTY$1;
2099
- /**
2100
- * Executes `fn` after `delay`, clearing any previously scheduled call.
2101
- */
2102
- request(fn) {
2103
- this.cancel();
2104
- this.currentId = scheduler.request(() => {
2105
- this.currentId = EMPTY$1;
2106
- fn();
2107
- });
2108
- }
2109
- cancel = () => {
2110
- if (this.currentId !== EMPTY$1) {
2111
- scheduler.cancel(this.currentId);
2112
- this.currentId = EMPTY$1;
2113
- }
2114
- };
2115
- disposeEffect = () => {
2116
- return this.cancel;
2117
- };
2118
- };
1673
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useAnimationsFinished.mjs
2119
1674
  /**
2120
- * A `requestAnimationFrame` with automatic cleanup and guard.
1675
+ * Executes a function once all animations have finished on the provided element.
1676
+ * If an animation is canceled, waits for any replacement animations before executing.
1677
+ * @param elementOrRef - The element to watch for animations.
1678
+ * @param waitForStartingStyleRemoved - Whether to wait for [data-starting-style] to be removed before checking for animations.
1679
+ * @returns A function that takes a callback to execute once all animations have finished, and an optional AbortSignal to abort the callback
2121
1680
  */
2122
- function useAnimationFrame() {
2123
- const timeout = useRefWithInit(AnimationFrame.create).current;
2124
- useOnMount(timeout.disposeEffect);
2125
- return timeout;
1681
+ function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false) {
1682
+ const frame = useAnimationFrame();
1683
+ return useStableCallback((fnToExecute, signal = null) => {
1684
+ frame.cancel();
1685
+ const element = resolveRef(elementOrRef);
1686
+ if (element == null) return;
1687
+ const resolvedElement = element;
1688
+ const done = () => {
1689
+ react_dom.flushSync(fnToExecute);
1690
+ };
1691
+ if (typeof resolvedElement.getAnimations !== "function" || globalThis.BASE_UI_ANIMATIONS_DISABLED) {
1692
+ fnToExecute();
1693
+ return;
1694
+ }
1695
+ function exec() {
1696
+ Promise.all(resolvedElement.getAnimations().map((animation) => animation.finished)).then(() => {
1697
+ if (!signal?.aborted) done();
1698
+ }, () => {
1699
+ if (signal?.aborted) return;
1700
+ if (resolvedElement.getAnimations().some((animation) => animation.pending || animation.playState !== "finished")) {
1701
+ exec();
1702
+ return;
1703
+ }
1704
+ done();
1705
+ });
1706
+ }
1707
+ if (waitForStartingStyleRemoved) {
1708
+ const startingStyleAttribute = "data-starting-style";
1709
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
1710
+ frame.request(exec);
1711
+ return;
1712
+ }
1713
+ const attributeObserver = new MutationObserver(() => {
1714
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
1715
+ attributeObserver.disconnect();
1716
+ exec();
1717
+ }
1718
+ });
1719
+ attributeObserver.observe(resolvedElement, {
1720
+ attributes: true,
1721
+ attributeFilter: [startingStyleAttribute]
1722
+ });
1723
+ signal?.addEventListener("abort", () => attributeObserver.disconnect(), { once: true });
1724
+ return;
1725
+ }
1726
+ frame.request(exec);
1727
+ });
2126
1728
  }
2127
1729
 
2128
1730
  //#endregion
2129
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useTransitionStatus.mjs
1731
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useOpenChangeComplete.mjs
2130
1732
  /**
2131
- * Provides a status string for CSS animations.
2132
- * @param open - a boolean that determines if the element is open.
2133
- * @param enableIdleState - a boolean that enables the `'idle'` state between `'starting'` and `'ending'`
1733
+ * Calls the provided function when the CSS open/close animation or transition completes.
2134
1734
  */
2135
- function useTransitionStatus(open, enableIdleState = false, deferEndingState = false) {
2136
- const [transitionStatus, setTransitionStatus] = react.useState(open && enableIdleState ? "idle" : void 0);
2137
- const [mounted, setMounted] = react.useState(open);
2138
- if (open && !mounted) {
2139
- setMounted(true);
2140
- setTransitionStatus("starting");
2141
- }
2142
- if (!open && mounted && transitionStatus !== "ending" && !deferEndingState) setTransitionStatus("ending");
2143
- if (!open && !mounted && transitionStatus === "ending") setTransitionStatus(void 0);
2144
- useIsoLayoutEffect(() => {
2145
- if (!open && mounted && transitionStatus !== "ending" && deferEndingState) {
2146
- const frame = AnimationFrame.request(() => {
2147
- setTransitionStatus("ending");
2148
- });
2149
- return () => {
2150
- AnimationFrame.cancel(frame);
2151
- };
2152
- }
2153
- }, [
2154
- open,
2155
- mounted,
2156
- transitionStatus,
2157
- deferEndingState
2158
- ]);
2159
- useIsoLayoutEffect(() => {
2160
- if (!open || enableIdleState) return;
2161
- const frame = AnimationFrame.request(() => {
2162
- setTransitionStatus(void 0);
2163
- });
2164
- return () => {
2165
- AnimationFrame.cancel(frame);
2166
- };
2167
- }, [enableIdleState, open]);
2168
- useIsoLayoutEffect(() => {
2169
- if (!open || !enableIdleState) return;
2170
- if (open && mounted && transitionStatus !== "idle") setTransitionStatus("starting");
2171
- const frame = AnimationFrame.request(() => {
2172
- setTransitionStatus("idle");
2173
- });
1735
+ function useOpenChangeComplete(parameters) {
1736
+ const { enabled = true, open, ref, onComplete: onCompleteParam } = parameters;
1737
+ const onComplete = useStableCallback(onCompleteParam);
1738
+ const runOnceAnimationsFinish = useAnimationsFinished(ref, open);
1739
+ react.useEffect(() => {
1740
+ if (!enabled) return;
1741
+ const abortController = new AbortController();
1742
+ runOnceAnimationsFinish(onComplete, abortController.signal);
2174
1743
  return () => {
2175
- AnimationFrame.cancel(frame);
1744
+ abortController.abort();
2176
1745
  };
2177
1746
  }, [
2178
- enableIdleState,
1747
+ enabled,
2179
1748
  open,
2180
- mounted,
2181
- transitionStatus
1749
+ onComplete,
1750
+ runOnceAnimationsFinish
2182
1751
  ]);
2183
- return {
2184
- mounted,
2185
- setMounted,
2186
- transitionStatus
2187
- };
2188
1752
  }
2189
1753
 
2190
1754
  //#endregion
2191
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/useCollapsibleRoot.mjs
2192
- function useCollapsibleRoot(parameters) {
2193
- const { open: openParam, defaultOpen, onOpenChange, disabled: disabled$1 } = parameters;
2194
- const [open, setOpen] = useControlled({
2195
- controlled: openParam,
2196
- default: defaultOpen,
2197
- name: "Collapsible",
2198
- state: "open"
1755
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/useCollapsiblePanel.mjs
1756
+ const EMPTY_DIMENSIONS = {
1757
+ height: void 0,
1758
+ width: void 0
1759
+ };
1760
+ function useCollapsiblePanel(parameters) {
1761
+ const { externalRef, hiddenUntilFound, id: idParam, keepMounted, mounted, onOpenChange, open, setMounted, setOpen, transitionStatus } = parameters;
1762
+ const panelRef = react.useRef(null);
1763
+ const animationTypeRef = react.useRef(null);
1764
+ const [dimensions, setDimensionsUnwrapped] = react.useState(EMPTY_DIMENSIONS);
1765
+ const lastMeasuredDimensionsRef = react.useRef(EMPTY_DIMENSIONS);
1766
+ const shouldSkipNextOpenRef = react.useRef(false);
1767
+ const shouldPreventMountAnimationRef = react.useRef(open);
1768
+ const shouldPreventActivityResumeAnimationRef = react.useRef(false);
1769
+ const [forcePanelIdle, setForcePanelIdle] = react.useState(false);
1770
+ const pendingTemporaryStyleRestoreRef = react.useRef(null);
1771
+ const mergedPanelRef = useMergedRefs(externalRef, panelRef);
1772
+ const latestOpenRef = useValueAsRef(open);
1773
+ const runOnceCloseAnimationsFinish = useAnimationsFinished(panelRef);
1774
+ const hidden = !open && !mounted;
1775
+ const panelTransitionStatus = forcePanelIdle ? "idle" : transitionStatus;
1776
+ const shouldPreventOpenAnimation = open && (shouldPreventMountAnimationRef.current || shouldPreventActivityResumeAnimationRef.current);
1777
+ const renderedDimensions = !open && mounted && animationTypeRef.current === "css-animation" && dimensions.height === void 0 && dimensions.width === void 0 ? lastMeasuredDimensionsRef.current : dimensions;
1778
+ const shouldPersistHiddenTransitionStyles = hiddenUntilFound && hidden && animationTypeRef.current !== "css-animation";
1779
+ const setDimensions = useStableCallback((nextDimensions, shouldCacheMeasurement = true) => {
1780
+ if (shouldCacheMeasurement) lastMeasuredDimensionsRef.current = nextDimensions;
1781
+ setDimensionsUnwrapped(nextDimensions);
2199
1782
  });
2200
- const { mounted, setMounted, transitionStatus } = useTransitionStatus(open, true, true);
2201
- const defaultPanelId = useBaseUiId();
2202
- const [registeredPanelId, setPanelIdState] = react.useState();
2203
- const panelId = registeredPanelId === null ? void 0 : registeredPanelId ?? defaultPanelId;
2204
- const handleTrigger = useStableCallback((event) => {
2205
- const nextOpen = !open;
2206
- const eventDetails = createChangeEventDetails(triggerPress, event.nativeEvent);
2207
- onOpenChange(nextOpen, eventDetails);
2208
- if (eventDetails.isCanceled) return;
2209
- setOpen(nextOpen);
1783
+ const restorePendingTemporaryStyle = useStableCallback(() => {
1784
+ pendingTemporaryStyleRestoreRef.current?.();
1785
+ pendingTemporaryStyleRestoreRef.current = null;
2210
1786
  });
2211
- return react.useMemo(() => ({
2212
- defaultPanelId,
2213
- disabled: disabled$1,
2214
- handleTrigger,
1787
+ const setPendingTemporaryStyleRestore = useStableCallback((restore) => {
1788
+ restorePendingTemporaryStyle();
1789
+ pendingTemporaryStyleRestoreRef.current = () => {
1790
+ pendingTemporaryStyleRestoreRef.current = null;
1791
+ restore();
1792
+ };
1793
+ });
1794
+ const markActivityResumeAnimationSuppressed = useStableCallback(() => {
1795
+ if (open && mounted && animationTypeRef.current === "css-animation") shouldPreventActivityResumeAnimationRef.current = true;
1796
+ });
1797
+ useIsoLayoutEffect(() => {
1798
+ if (!forcePanelIdle || transitionStatus === "starting") return;
1799
+ setForcePanelIdle(false);
1800
+ }, [forcePanelIdle, transitionStatus]);
1801
+ react.useEffect(() => {
1802
+ return () => {
1803
+ markActivityResumeAnimationSuppressed();
1804
+ restorePendingTemporaryStyle();
1805
+ };
1806
+ }, [markActivityResumeAnimationSuppressed, restorePendingTemporaryStyle]);
1807
+ useIsoLayoutEffect(() => {
1808
+ const panel = panelRef.current;
1809
+ if (!panel) return;
1810
+ if (!open && pendingTemporaryStyleRestoreRef.current) restorePendingTemporaryStyle();
1811
+ const animationType = getAnimationType(panel, shouldPreventOpenAnimation);
1812
+ animationTypeRef.current = animationType;
1813
+ if (open && transitionStatus === "idle" && shouldPreventMountAnimationRef.current && animationType === "css-animation") {
1814
+ lastMeasuredDimensionsRef.current = getDimensions$1(panel);
1815
+ return;
1816
+ }
1817
+ if (open && transitionStatus === "starting") {
1818
+ const skipNextOpen = shouldSkipNextOpenRef.current;
1819
+ shouldSkipNextOpenRef.current = false;
1820
+ if (animationType === "none") {
1821
+ setDimensions(getDimensions$1(panel));
1822
+ setForcePanelIdle(true);
1823
+ return;
1824
+ }
1825
+ if (animationType === "css-transition") {
1826
+ const restoreLayoutStyles = resetLayoutStyles(panel);
1827
+ setDimensions(getDimensions$1(panel));
1828
+ if (!skipNextOpen) return restoreLayoutStyles;
1829
+ setPendingTemporaryStyleRestore(setTemporaryStyle(panel, "transition-duration", "0s"));
1830
+ setForcePanelIdle(true);
1831
+ return restoreLayoutStyles;
1832
+ }
1833
+ setDimensions(getDimensions$1(panel));
1834
+ const restoreAnimationName = setTemporaryStyle(panel, "animation-name", "none");
1835
+ if (!skipNextOpen) {
1836
+ restoreAnimationName();
1837
+ return;
1838
+ }
1839
+ const restoreAnimationDuration = setTemporaryStyle(panel, "animation-duration", "0s");
1840
+ restoreAnimationName();
1841
+ setPendingTemporaryStyleRestore(restoreAnimationDuration);
1842
+ setForcePanelIdle(true);
1843
+ return;
1844
+ }
1845
+ if (!open && mounted && (transitionStatus === "idle" || transitionStatus === "starting")) {
1846
+ shouldPreventMountAnimationRef.current = false;
1847
+ shouldPreventActivityResumeAnimationRef.current = false;
1848
+ if (animationType === "none") {
1849
+ setDimensions(EMPTY_DIMENSIONS, false);
1850
+ setMounted(false);
1851
+ return;
1852
+ }
1853
+ setDimensions(getDimensions$1(panel));
1854
+ return;
1855
+ }
1856
+ if (transitionStatus !== "ending") return;
1857
+ if (animationType === "none") {
1858
+ setMounted(false);
1859
+ return;
1860
+ }
1861
+ const nextDimensions = getDimensions$1(panel);
1862
+ if (!(nextDimensions.height > 0 || nextDimensions.width > 0)) {
1863
+ setMounted(false);
1864
+ return;
1865
+ }
1866
+ setDimensions(nextDimensions);
1867
+ if (animationType === "css-animation") setTemporaryStyle(panel, "animation-name", "none")();
1868
+ }, [
2215
1869
  mounted,
2216
1870
  open,
2217
- panelId,
1871
+ restorePendingTemporaryStyle,
1872
+ setDimensions,
2218
1873
  setMounted,
2219
- setOpen,
2220
- setPanelIdState,
1874
+ setPendingTemporaryStyleRestore,
1875
+ shouldPreventOpenAnimation,
2221
1876
  transitionStatus
2222
- }), [
2223
- defaultPanelId,
2224
- disabled$1,
2225
- handleTrigger,
1877
+ ]);
1878
+ useOpenChangeComplete({
1879
+ enabled: open && mounted && panelTransitionStatus === "idle",
1880
+ open: true,
1881
+ ref: panelRef,
1882
+ onComplete() {
1883
+ if (!open) return;
1884
+ setDimensions(EMPTY_DIMENSIONS, false);
1885
+ }
1886
+ });
1887
+ react.useEffect(() => {
1888
+ if (open || !mounted || panelTransitionStatus !== "ending") return;
1889
+ if (!panelRef.current) return;
1890
+ const abortController = new AbortController();
1891
+ let endingStyleFrame = -1;
1892
+ function handleComplete() {
1893
+ if (latestOpenRef.current) return;
1894
+ setMounted(false);
1895
+ setDimensions(EMPTY_DIMENSIONS, false);
1896
+ }
1897
+ endingStyleFrame = AnimationFrame.request(() => {
1898
+ runOnceCloseAnimationsFinish(handleComplete, abortController.signal);
1899
+ });
1900
+ return () => {
1901
+ AnimationFrame.cancel(endingStyleFrame);
1902
+ abortController.abort();
1903
+ };
1904
+ }, [
1905
+ latestOpenRef,
2226
1906
  mounted,
2227
1907
  open,
2228
- panelId,
2229
- setMounted,
2230
- setOpen,
2231
- setPanelIdState,
2232
- transitionStatus
1908
+ panelTransitionStatus,
1909
+ runOnceCloseAnimationsFinish,
1910
+ setDimensions,
1911
+ setMounted
2233
1912
  ]);
2234
- }
2235
-
2236
- //#endregion
2237
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/CollapsibleRootContext.mjs
2238
- const CollapsibleRootContext = /* @__PURE__ */ react.createContext(void 0);
2239
- function useCollapsibleRootContext() {
2240
- const context = react.useContext(CollapsibleRootContext);
2241
- if (context === void 0) throw new Error(formatErrorMessage_default(15));
2242
- return context;
2243
- }
2244
-
2245
- //#endregion
2246
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/stateAttributesMapping.mjs
2247
- let TransitionStatusDataAttributes = /* @__PURE__ */ function(TransitionStatusDataAttributes$1) {
2248
- /**
2249
- * Present when the component begins animating in.
2250
- */
2251
- TransitionStatusDataAttributes$1["startingStyle"] = "data-starting-style";
2252
- /**
2253
- * Present when the component is animating out.
2254
- */
2255
- TransitionStatusDataAttributes$1["endingStyle"] = "data-ending-style";
2256
- return TransitionStatusDataAttributes$1;
2257
- }({});
2258
- const STARTING_HOOK = { "data-starting-style": "" };
2259
- const ENDING_HOOK = { "data-ending-style": "" };
2260
- const transitionStatusMapping = { transitionStatus(value) {
2261
- if (value === "starting") return STARTING_HOOK;
2262
- if (value === "ending") return ENDING_HOOK;
2263
- return null;
2264
- } };
1913
+ useIsoLayoutEffect(() => {
1914
+ const panel = panelRef.current;
1915
+ if (!panel || !hiddenUntilFound || !hidden) return;
1916
+ panel.setAttribute("hidden", "until-found");
1917
+ }, [hidden, hiddenUntilFound]);
1918
+ react.useEffect(function registerBeforeMatchListener() {
1919
+ const panel = panelRef.current;
1920
+ if (!panel) return;
1921
+ function handleBeforeMatch(event) {
1922
+ const eventDetails = createChangeEventDetails(none, event);
1923
+ onOpenChange(true, eventDetails);
1924
+ if (eventDetails.isCanceled) return;
1925
+ shouldSkipNextOpenRef.current = true;
1926
+ setOpen(true);
1927
+ }
1928
+ return addEventListener(panel, "beforematch", handleBeforeMatch);
1929
+ }, [onOpenChange, setOpen]);
1930
+ const shouldRender = keepMounted || hiddenUntilFound || mounted || open;
1931
+ return {
1932
+ height: renderedDimensions.height,
1933
+ props: {
1934
+ ...shouldPersistHiddenTransitionStyles ? { [CollapsiblePanelDataAttributes.startingStyle]: "" } : void 0,
1935
+ hidden,
1936
+ id: idParam
1937
+ },
1938
+ ref: mergedPanelRef,
1939
+ shouldPreventOpenAnimation,
1940
+ shouldRender,
1941
+ transitionStatus: panelTransitionStatus,
1942
+ width: renderedDimensions.width
1943
+ };
1944
+ }
1945
+ function getDimensions$1(element) {
1946
+ return {
1947
+ height: element.scrollHeight,
1948
+ width: element.scrollWidth
1949
+ };
1950
+ }
1951
+ function getAnimationType(element, hasSuppressedMountAnimation) {
1952
+ const panelStyles = getWindow(element).getComputedStyle(element);
1953
+ const hasAnimation = (panelStyles.animationName.split(",").map((name) => name.trim()).some((name) => name !== "" && name !== "none") || hasSuppressedMountAnimation) && hasNonZeroDuration(panelStyles.animationDuration);
1954
+ const hasTransition = hasNonZeroDuration(panelStyles.transitionDuration);
1955
+ if (hasAnimation && hasTransition) return "css-transition";
1956
+ if (hasTransition) return "css-transition";
1957
+ if (hasAnimation) return "css-animation";
1958
+ return "none";
1959
+ }
1960
+ function hasNonZeroDuration(value) {
1961
+ return value.split(",").map((part) => part.trim()).some((part) => part !== "" && Number.parseFloat(part) > 0);
1962
+ }
1963
+ /**
1964
+ * Temporarily overrides an inline style property and returns a cleanup that
1965
+ * restores the previous inline value and priority.
1966
+ * @param element - The element whose inline style should be updated.
1967
+ * @param property - The CSS property name to override.
1968
+ * @param value - The temporary value to assign.
1969
+ * @returns A cleanup function that restores the original inline style state.
1970
+ */
1971
+ function setTemporaryStyle(element, property, value) {
1972
+ const previousValue = element.style.getPropertyValue(property);
1973
+ const previousPriority = element.style.getPropertyPriority(property);
1974
+ element.style.setProperty(property, value);
1975
+ return () => {
1976
+ if (previousValue === "") {
1977
+ element.style.removeProperty(property);
1978
+ return;
1979
+ }
1980
+ element.style.setProperty(property, previousValue, previousPriority);
1981
+ };
1982
+ }
1983
+ /**
1984
+ * Temporarily resets inline alignment styles that can distort scroll-based
1985
+ * size measurements, then restores them on the next animation frame.
1986
+ * @param element - The panel element being measured.
1987
+ * @returns A cleanup function that cancels the scheduled restore and reapplies
1988
+ * the original inline layout styles immediately.
1989
+ */
1990
+ function resetLayoutStyles(element) {
1991
+ const originalLayoutStyles = {
1992
+ "justify-content": element.style.justifyContent,
1993
+ "align-items": element.style.alignItems,
1994
+ "align-content": element.style.alignContent,
1995
+ "justify-items": element.style.justifyItems
1996
+ };
1997
+ Object.keys(originalLayoutStyles).forEach((key) => {
1998
+ element.style.setProperty(key, "initial", "important");
1999
+ });
2000
+ function restoreLayoutStyles() {
2001
+ Object.entries(originalLayoutStyles).forEach(([key, value]) => {
2002
+ if (value === "") {
2003
+ element.style.removeProperty(key);
2004
+ return;
2005
+ }
2006
+ element.style.setProperty(key, value);
2007
+ });
2008
+ }
2009
+ const frame = AnimationFrame.request(restoreLayoutStyles);
2010
+ return () => {
2011
+ AnimationFrame.cancel(frame);
2012
+ restoreLayoutStyles();
2013
+ };
2014
+ }
2265
2015
 
2266
2016
  //#endregion
2267
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/CollapsiblePanelDataAttributes.mjs
2268
- let CollapsiblePanelDataAttributes = function(CollapsiblePanelDataAttributes$1) {
2269
- /**
2270
- * Present when the collapsible panel is open.
2271
- */
2272
- CollapsiblePanelDataAttributes$1["open"] = "data-open";
2273
- /**
2274
- * Present when the collapsible panel is closed.
2275
- */
2276
- CollapsiblePanelDataAttributes$1["closed"] = "data-closed";
2277
- /**
2278
- * Present when the panel begins animating in.
2279
- */
2280
- CollapsiblePanelDataAttributes$1[CollapsiblePanelDataAttributes$1["startingStyle"] = TransitionStatusDataAttributes.startingStyle] = "startingStyle";
2017
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/CollapsiblePanelCssVars.mjs
2018
+ let CollapsiblePanelCssVars = /* @__PURE__ */ function(CollapsiblePanelCssVars$1) {
2281
2019
  /**
2282
- * Present when the panel is animating out.
2020
+ * The collapsible panel's height.
2021
+ * @type {number}
2283
2022
  */
2284
- CollapsiblePanelDataAttributes$1[CollapsiblePanelDataAttributes$1["endingStyle"] = TransitionStatusDataAttributes.endingStyle] = "endingStyle";
2285
- return CollapsiblePanelDataAttributes$1;
2286
- }({});
2287
-
2288
- //#endregion
2289
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/trigger/CollapsibleTriggerDataAttributes.mjs
2290
- let CollapsibleTriggerDataAttributes = /* @__PURE__ */ function(CollapsibleTriggerDataAttributes$1) {
2023
+ CollapsiblePanelCssVars$1["collapsiblePanelHeight"] = "--collapsible-panel-height";
2291
2024
  /**
2292
- * Present when the collapsible panel is open.
2025
+ * The collapsible panel's width.
2026
+ * @type {number}
2293
2027
  */
2294
- CollapsibleTriggerDataAttributes$1["panelOpen"] = "data-panel-open";
2295
- return CollapsibleTriggerDataAttributes$1;
2028
+ CollapsiblePanelCssVars$1["collapsiblePanelWidth"] = "--collapsible-panel-width";
2029
+ return CollapsiblePanelCssVars$1;
2296
2030
  }({});
2297
2031
 
2298
2032
  //#endregion
2299
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/collapsibleOpenStateMapping.mjs
2300
- const PANEL_OPEN_HOOK = { [CollapsiblePanelDataAttributes.open]: "" };
2301
- const PANEL_CLOSED_HOOK = { [CollapsiblePanelDataAttributes.closed]: "" };
2302
- const triggerOpenStateMapping$1 = { open(value) {
2303
- if (value) return { [CollapsibleTriggerDataAttributes.panelOpen]: "" };
2304
- return null;
2305
- } };
2306
- const collapsibleOpenStateMapping = { open(value) {
2307
- if (value) return PANEL_OPEN_HOOK;
2308
- return PANEL_CLOSED_HOOK;
2309
- } };
2310
-
2311
- //#endregion
2312
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/stateAttributesMapping.mjs
2313
- const collapsibleStateAttributesMapping = {
2314
- ...collapsibleOpenStateMapping,
2315
- ...transitionStatusMapping
2316
- };
2317
-
2318
- //#endregion
2319
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/root/CollapsibleRoot.mjs
2033
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/CollapsiblePanel.mjs
2320
2034
  /**
2321
- * Groups all parts of the collapsible.
2035
+ * A panel with the collapsible contents.
2322
2036
  * Renders a `<div>` element.
2323
2037
  *
2324
2038
  * Documentation: [Base UI Collapsible](https://base-ui.com/react/components/collapsible)
2325
2039
  */
2326
- const CollapsibleRoot = /* @__PURE__ */ react.forwardRef(function CollapsibleRoot$1(componentProps, forwardedRef) {
2327
- const { render, className, defaultOpen = false, disabled: disabled$1 = false, onOpenChange: onOpenChangeProp, open, style,...elementProps } = componentProps;
2328
- const onOpenChange = useStableCallback(onOpenChangeProp);
2329
- const collapsible = useCollapsibleRoot({
2330
- open,
2331
- defaultOpen,
2040
+ const CollapsiblePanel = /* @__PURE__ */ react.forwardRef(function CollapsiblePanel$1(componentProps, forwardedRef) {
2041
+ const { className, hiddenUntilFound: hiddenUntilFoundProp, keepMounted: keepMountedProp, render, id: idProp, style,...elementProps } = componentProps;
2042
+ const { defaultPanelId, mounted, onOpenChange, open, setMounted, setPanelIdState, setOpen, state, transitionStatus } = useCollapsibleRootContext();
2043
+ const hiddenUntilFound = hiddenUntilFoundProp ?? false;
2044
+ const keepMounted = keepMountedProp ?? false;
2045
+ const registeredId = idProp || void 0;
2046
+ const id = registeredId ?? defaultPanelId;
2047
+ useIsoLayoutEffect(() => {
2048
+ setPanelIdState((currentId) => registeredId ?? (currentId === null ? void 0 : currentId));
2049
+ return () => {
2050
+ setPanelIdState((currentId) => currentId === registeredId ? null : currentId);
2051
+ };
2052
+ }, [registeredId, setPanelIdState]);
2053
+ const { height, props, ref, shouldPreventOpenAnimation, shouldRender, transitionStatus: panelTransitionStatus, width } = useCollapsiblePanel({
2054
+ externalRef: forwardedRef,
2055
+ hiddenUntilFound,
2056
+ id,
2057
+ keepMounted,
2058
+ mounted,
2332
2059
  onOpenChange,
2333
- disabled: disabled$1
2060
+ open,
2061
+ setMounted,
2062
+ setOpen,
2063
+ transitionStatus
2334
2064
  });
2335
- const state = react.useMemo(() => ({
2336
- open: collapsible.open,
2337
- disabled: collapsible.disabled,
2338
- transitionStatus: collapsible.transitionStatus
2339
- }), [
2340
- collapsible.open,
2341
- collapsible.disabled,
2342
- collapsible.transitionStatus
2343
- ]);
2344
- const contextValue = react.useMemo(() => ({
2345
- ...collapsible,
2346
- onOpenChange,
2347
- state
2348
- }), [
2349
- collapsible,
2350
- onOpenChange,
2351
- state
2352
- ]);
2353
- const element = useRenderElement("div", componentProps, {
2354
- state,
2355
- ref: forwardedRef,
2356
- props: elementProps,
2065
+ const panelState = {
2066
+ ...state,
2067
+ transitionStatus: panelTransitionStatus
2068
+ };
2069
+ const resolvedStyle = resolveStyle(style, panelState);
2070
+ const element = useRenderElement("div", {
2071
+ ...componentProps,
2072
+ style: void 0
2073
+ }, {
2074
+ state: panelState,
2075
+ ref,
2076
+ props: [
2077
+ props,
2078
+ { style: {
2079
+ [CollapsiblePanelCssVars.collapsiblePanelHeight]: height === void 0 ? "auto" : `${height}px`,
2080
+ [CollapsiblePanelCssVars.collapsiblePanelWidth]: width === void 0 ? "auto" : `${width}px`
2081
+ } },
2082
+ elementProps,
2083
+ resolvedStyle ? { style: resolvedStyle } : void 0,
2084
+ shouldPreventOpenAnimation ? { style: { animationName: "none" } } : void 0
2085
+ ],
2357
2086
  stateAttributesMapping: collapsibleStateAttributesMapping
2358
2087
  });
2359
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleRootContext.Provider, {
2360
- value: contextValue,
2361
- children: element
2362
- });
2088
+ if (!shouldRender) return null;
2089
+ return element;
2363
2090
  });
2364
2091
 
2365
2092
  //#endregion
2366
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/trigger/CollapsibleTrigger.mjs
2367
- const stateAttributesMapping$1 = {
2368
- ...triggerOpenStateMapping$1,
2369
- ...transitionStatusMapping
2370
- };
2093
+ //#region src/client/icons.ts
2094
+ /** Rendered when a host generation has neither name: the panel stays usable. */
2095
+ const MissingIcon = () => null;
2371
2096
  /**
2372
- * A button that opens and closes the collapsible panel.
2373
- * Renders a `<button>` element.
2374
- *
2375
- * Documentation: [Base UI Collapsible](https://base-ui.com/react/components/collapsible)
2376
- */
2377
- const CollapsibleTrigger = /* @__PURE__ */ react.forwardRef(function CollapsibleTrigger$1(componentProps, forwardedRef) {
2378
- const { panelId, open, handleTrigger, state, disabled: contextDisabled } = useCollapsibleRootContext();
2379
- const { className, disabled: disabled$1 = contextDisabled, render, nativeButton = true, style,...elementProps } = componentProps;
2380
- const { getButtonProps, buttonRef } = useButton({
2381
- disabled: disabled$1,
2382
- focusableWhenDisabled: true,
2383
- native: nativeButton
2384
- });
2385
- return useRenderElement("button", componentProps, {
2386
- state,
2387
- ref: [forwardedRef, buttonRef],
2388
- props: [
2389
- {
2390
- "aria-controls": open ? panelId : void 0,
2391
- "aria-expanded": open,
2392
- onClick: handleTrigger
2393
- },
2394
- elementProps,
2395
- getButtonProps
2396
- ],
2397
- stateAttributesMapping: stateAttributesMapping$1
2398
- });
2399
- });
2400
-
2401
- //#endregion
2402
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/addEventListener.mjs
2097
+ * Pick the first export name the host's primitives package actually provides.
2098
+ * Exported separately from the module-level constants so tests can drive every
2099
+ * branch with a fake table.
2100
+ */
2101
+ function pickIcon(table$1, modern, legacy) {
2102
+ const found = table$1[modern] ?? table$1[legacy];
2103
+ return typeof found === "function" ? found : MissingIcon;
2104
+ }
2105
+ const table = __deepseek_ai_dsh_client_ui_primitives;
2403
2106
  /**
2404
- * Adds an event listener and returns a cleanup function to remove it.
2107
+ * Every icon the panel renders, with both generations' export names side by
2108
+ * side: `modern` is the 0.1.7+ stroke-weight name, `legacy` the pixel-suffixed
2109
+ * name it replaced. Kept as data (instead of being inlined into the constants
2110
+ * below) so tests can pin each half against the export list that really ships
2111
+ * it — the modern names against the installed package, the legacy names
2112
+ * against the last release that still had them.
2405
2113
  */
2406
- function addEventListener(target, type, listener, options) {
2407
- target.addEventListener(type, listener, options);
2408
- return () => {
2409
- target.removeEventListener(type, listener, options);
2410
- };
2114
+ const ICON_NAME_PAIRS = {
2115
+ IconSkill: {
2116
+ modern: "IconSkillOutlineRegular",
2117
+ legacy: "IconSkillOutline16"
2118
+ },
2119
+ IconSparkle: {
2120
+ modern: "IconSparkleRegular",
2121
+ legacy: "IconSparkle16"
2122
+ },
2123
+ IconCordisPlugin: {
2124
+ modern: "IconCordisPluginOutlineRegular",
2125
+ legacy: "IconCordisPluginOutline14"
2126
+ },
2127
+ IconSliders: {
2128
+ modern: "IconPersonalizationOutlineRegular",
2129
+ legacy: "IconPersonalizationOutline16"
2130
+ },
2131
+ IconPanelLeft: {
2132
+ modern: "IconPanelLeftOutlineRegular",
2133
+ legacy: "IconPanelLeftOutline16"
2134
+ },
2135
+ IconPlus: {
2136
+ modern: "IconPlusOutlineRegular",
2137
+ legacy: "IconPlusOutline16"
2138
+ },
2139
+ IconFolderClose: {
2140
+ modern: "IconFolderCloseRegular",
2141
+ legacy: "IconFolderClose16"
2142
+ },
2143
+ IconSearch: {
2144
+ modern: "IconSearchOutlineRegular",
2145
+ legacy: "IconSearchOutline16"
2146
+ },
2147
+ IconRefresh: {
2148
+ modern: "IconRefreshOutlineRegular",
2149
+ legacy: "IconRefreshOutline14"
2150
+ },
2151
+ IconChevronDown: {
2152
+ modern: "IconChevronDownOutlineRegular",
2153
+ legacy: "IconChevronDownOutline14"
2154
+ },
2155
+ IconChevronUp: {
2156
+ modern: "IconChevronUpOutlineRegular",
2157
+ legacy: "IconChevronUpOutline14"
2158
+ },
2159
+ IconSettings: {
2160
+ modern: "IconSettingsOutlineMedium",
2161
+ legacy: "IconSettingsOutline16"
2162
+ },
2163
+ IconTriangleRight: {
2164
+ modern: "IconTriangleRightFillRegular",
2165
+ legacy: "IconTriangleRightFill14"
2166
+ }
2167
+ };
2168
+ /** Resolve one pair against the host's own export table. */
2169
+ function resolveIcon(pair) {
2170
+ return pickIcon(table, pair.modern, pair.legacy);
2171
+ }
2172
+ const IconSkill = resolveIcon(ICON_NAME_PAIRS.IconSkill);
2173
+ const IconSparkle = resolveIcon(ICON_NAME_PAIRS.IconSparkle);
2174
+ const IconCordisPlugin = resolveIcon(ICON_NAME_PAIRS.IconCordisPlugin);
2175
+ const IconSliders = resolveIcon(ICON_NAME_PAIRS.IconSliders);
2176
+ const IconPanelLeft = resolveIcon(ICON_NAME_PAIRS.IconPanelLeft);
2177
+ const IconPlus = resolveIcon(ICON_NAME_PAIRS.IconPlus);
2178
+ const IconFolderClose = resolveIcon(ICON_NAME_PAIRS.IconFolderClose);
2179
+ const IconSearch = resolveIcon(ICON_NAME_PAIRS.IconSearch);
2180
+ const IconRefresh = resolveIcon(ICON_NAME_PAIRS.IconRefresh);
2181
+ const IconChevronDown = resolveIcon(ICON_NAME_PAIRS.IconChevronDown);
2182
+ const IconChevronUp = resolveIcon(ICON_NAME_PAIRS.IconChevronUp);
2183
+ const IconSettings = resolveIcon(ICON_NAME_PAIRS.IconSettings);
2184
+ const IconTriangleRight = resolveIcon(ICON_NAME_PAIRS.IconTriangleRight);
2185
+ /**
2186
+ * Whether the host ships the 0.1.7 stroke-weight icon set. Exported as a
2187
+ * function so tests can drive both branches; the module constant resolves it
2188
+ * against the real package.
2189
+ *
2190
+ * One consumer: the footer settings entry. The `settings.open` keybinding that
2191
+ * entry drives shipped in the SAME host generation as the renamed icon set
2192
+ * (verified: 0.1.6's settings bundle has no such binding), so this is the
2193
+ * closest client-visible signal that the shortcut exists. If a future host
2194
+ * renames icons again this reads false and the entry hides — the safe
2195
+ * direction.
2196
+ */
2197
+ function hasModernShell(table$1) {
2198
+ return typeof table$1["IconSettingsOutlineRegular"] === "function";
2411
2199
  }
2200
+ const HOST_HAS_MODERN_SHELL = hasModernShell(table);
2412
2201
 
2413
2202
  //#endregion
2414
- //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/useValueAsRef.mjs
2203
+ //#region src/client/disclosure-row.ts
2415
2204
  /**
2416
- * Untracks the provided value by turning it into a ref to remove its reactivity.
2205
+ * The disclosure chevron, taken from the host's icon set instead of drawn here.
2417
2206
  *
2418
- * Used to access the passed value inside `React.useEffect` without causing the effect to re-run when the value changes.
2207
+ * The host's own DisclosureRow primitive — the same affordance, used by the
2208
+ * conversation, cordis, tool and workflow surfaces — points a DOWN chevron while
2209
+ * the row is closed and an UP chevron while it is open, at the host icons'
2210
+ * default 14px. Drawn here, it was a 12px path with a 1.4px stroke: a geometry
2211
+ * no host surface uses, which reads as a foreign glyph next to the host's own.
2212
+ *
2213
+ * Kept in one place because the two panels had already drifted apart in
2214
+ * geometry once — exactly the failure a shared control prevents.
2419
2215
  */
2420
- function useValueAsRef(value) {
2421
- const latest = useRefWithInit(createLatestRef, value).current;
2422
- latest.next = value;
2423
- useIsoLayoutEffect(latest.effect);
2424
- return latest;
2216
+ function chevronIcon(open) {
2217
+ return open ? react.createElement(IconChevronUp, { size: 14 }) : react.createElement(IconChevronDown, { size: 14 });
2425
2218
  }
2426
- function createLatestRef(value) {
2427
- const latest = {
2428
- current: value,
2429
- next: value,
2430
- effect: () => {
2431
- latest.current = latest.next;
2432
- }
2433
- };
2434
- return latest;
2435
- }
2436
-
2437
- //#endregion
2438
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/utils/resolveRef.mjs
2439
2219
  /**
2440
- * If the provided argument is a ref object, returns its `current` value.
2441
- * Otherwise, returns the argument itself.
2220
+ * The row's leading box, laid out exactly like the host's `DisclosureRow`: one
2221
+ * fixed 18px square holds BOTH the domain glyph and the disclosure chevron, and
2222
+ * hovering the row swaps the glyph out for the chevron in place. Two reasons to
2223
+ * copy that instead of adding a second box:
2224
+ *
2225
+ * - no layout shift — the box never changes size, so nothing reflows on hover;
2226
+ * - a list of rows reads as named capabilities rather than as a column of
2227
+ * arrows, which is what an always-visible chevron per row produces.
2228
+ *
2229
+ * While the row is OPEN the host shows the chevron alone (its `leading` is the
2230
+ * up-chevron, not the glyph), so the same swap is mirrored here.
2442
2231
  */
2443
- function resolveRef(maybeRef) {
2444
- if (maybeRef == null) return maybeRef;
2445
- return "current" in maybeRef ? maybeRef.current : maybeRef;
2232
+ function leadingBox(children) {
2233
+ return react.createElement("span", {
2234
+ className: "ci-leading",
2235
+ "aria-hidden": true
2236
+ }, children);
2237
+ }
2238
+ function glyph(className, child, key) {
2239
+ return react.createElement("span", {
2240
+ className,
2241
+ "aria-hidden": true,
2242
+ ...key === void 0 ? {} : { key }
2243
+ }, child);
2244
+ }
2245
+ /** The leading slot for a row that has a domain glyph. */
2246
+ function glyphLeading(icon, open) {
2247
+ if (open) return leadingBox(glyph("ci-chevron", chevronIcon(true)));
2248
+ return leadingBox([glyph("ci-row-icon", icon, "icon"), glyph("ci-chevron ci-chevron-hover", chevronIcon(false), "chevron")]);
2249
+ }
2250
+ /** The leading slot for a row with no glyph: the chevron, as before. */
2251
+ function chevronLeading(open) {
2252
+ return react.createElement("span", {
2253
+ className: "ci-chevron",
2254
+ "aria-hidden": true
2255
+ }, chevronIcon(open));
2446
2256
  }
2447
-
2448
- //#endregion
2449
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useAnimationsFinished.mjs
2450
2257
  /**
2451
- * Executes a function once all animations have finished on the provided element.
2452
- * If an animation is canceled, waits for any replacement animations before executing.
2453
- * @param elementOrRef - The element to watch for animations.
2454
- * @param waitForStartingStyleRemoved - Whether to wait for [data-starting-style] to be removed before checking for animations.
2455
- * @returns A function that takes a callback to execute once all animations have finished, and an optional AbortSignal to abort the callback
2258
+ * The leading slot of one expandable row.
2259
+ *
2260
+ * Exported so the panel's own row builder — which needs the same slot in a
2261
+ * different component tree — renders it from here instead of re-implementing
2262
+ * it. That is the drift this module exists to prevent: the two panels once
2263
+ * carried two different chevrons.
2456
2264
  */
2457
- function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false) {
2458
- const frame = useAnimationFrame();
2459
- return useStableCallback((fnToExecute, signal = null) => {
2460
- frame.cancel();
2461
- const element = resolveRef(elementOrRef);
2462
- if (element == null) return;
2463
- const resolvedElement = element;
2464
- const done = () => {
2465
- react_dom.flushSync(fnToExecute);
2466
- };
2467
- if (typeof resolvedElement.getAnimations !== "function" || globalThis.BASE_UI_ANIMATIONS_DISABLED) {
2468
- fnToExecute();
2469
- return;
2470
- }
2471
- function exec() {
2472
- Promise.all(resolvedElement.getAnimations().map((animation) => animation.finished)).then(() => {
2473
- if (!signal?.aborted) done();
2474
- }, () => {
2475
- if (signal?.aborted) return;
2476
- if (resolvedElement.getAnimations().some((animation) => animation.pending || animation.playState !== "finished")) {
2477
- exec();
2478
- return;
2479
- }
2480
- done();
2481
- });
2482
- }
2483
- if (waitForStartingStyleRemoved) {
2484
- const startingStyleAttribute = "data-starting-style";
2485
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
2486
- frame.request(exec);
2487
- return;
2488
- }
2489
- const attributeObserver = new MutationObserver(() => {
2490
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
2491
- attributeObserver.disconnect();
2492
- exec();
2493
- }
2494
- });
2495
- attributeObserver.observe(resolvedElement, {
2496
- attributes: true,
2497
- attributeFilter: [startingStyleAttribute]
2498
- });
2499
- signal?.addEventListener("abort", () => attributeObserver.disconnect(), { once: true });
2500
- return;
2501
- }
2502
- frame.request(exec);
2503
- });
2265
+ function leadingFor(icon, open) {
2266
+ return icon === void 0 ? chevronLeading(open) : glyphLeading(icon, open);
2267
+ }
2268
+ /** The leading slot of a row with nothing to reveal: the glyph alone. */
2269
+ function leadingStatic(icon) {
2270
+ return leadingBox(glyph("ci-row-icon", icon));
2504
2271
  }
2505
-
2506
- //#endregion
2507
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useOpenChangeComplete.mjs
2508
2272
  /**
2509
- * Calls the provided function when the CSS open/close animation or transition completes.
2273
+ * One capability row that may reveal detail.
2274
+ *
2275
+ * Both panels show the same kind of thing — a name, a switch, and detail worth
2276
+ * hiding until asked for — so both get the same affordance from one place. A
2277
+ * row with no detail renders no trigger at all rather than an empty one, and
2278
+ * takes a spacer so its name still lines up with the rows that do.
2510
2279
  */
2511
- function useOpenChangeComplete(parameters) {
2512
- const { enabled = true, open, ref, onComplete: onCompleteParam } = parameters;
2513
- const onComplete = useStableCallback(onCompleteParam);
2514
- const runOnceAnimationsFinish = useAnimationsFinished(ref, open);
2515
- react.useEffect(() => {
2516
- if (!enabled) return;
2517
- const abortController = new AbortController();
2518
- runOnceAnimationsFinish(onComplete, abortController.signal);
2519
- return () => {
2520
- abortController.abort();
2521
- };
2522
- }, [
2523
- enabled,
2524
- open,
2525
- onComplete,
2526
- runOnceAnimationsFinish
2527
- ]);
2280
+ function disclosureRow(options) {
2281
+ const hasIcon = options.icon !== void 0;
2282
+ if (!(options.detail !== void 0 && options.detail !== null && options.detail !== "")) return react.createElement("div", {
2283
+ className: options.className,
2284
+ ...options.style === void 0 ? {} : { style: options.style }
2285
+ }, react.createElement("div", { className: options.headerClassName }, hasIcon ? leadingStatic(options.icon) : react.createElement("span", {
2286
+ "aria-hidden": true,
2287
+ ...options.spacerClassName === void 0 ? { style: {
2288
+ width: "18px",
2289
+ flex: "none"
2290
+ } } : { className: options.spacerClassName }
2291
+ }), options.heading, ...options.actions));
2292
+ const disclosure = resolveDisclosure(options.expanded, options.filtering);
2293
+ return react.createElement(CollapsibleRoot, {
2294
+ open: disclosure.open,
2295
+ onOpenChange: options.onOpenChange,
2296
+ className: options.className,
2297
+ ...options.style === void 0 ? {} : { style: options.style }
2298
+ }, react.createElement("div", { className: options.headerClassName }, react.createElement(CollapsibleTrigger, {
2299
+ className: "ci-disclosure-trigger",
2300
+ disabled: disclosure.disabled,
2301
+ "aria-label": options.triggerLabel
2302
+ }, hasIcon ? leadingFor(options.icon, disclosure.open) : chevronLeading(disclosure.open), options.heading), ...options.actions), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, options.detail));
2528
2303
  }
2529
2304
 
2530
2305
  //#endregion
2531
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/useCollapsiblePanel.mjs
2532
- const EMPTY_DIMENSIONS = {
2533
- height: void 0,
2534
- width: void 0
2535
- };
2536
- function useCollapsiblePanel(parameters) {
2537
- const { externalRef, hiddenUntilFound, id: idParam, keepMounted, mounted, onOpenChange, open, setMounted, setOpen, transitionStatus } = parameters;
2538
- const panelRef = react.useRef(null);
2539
- const animationTypeRef = react.useRef(null);
2540
- const [dimensions, setDimensionsUnwrapped] = react.useState(EMPTY_DIMENSIONS);
2541
- const lastMeasuredDimensionsRef = react.useRef(EMPTY_DIMENSIONS);
2542
- const shouldSkipNextOpenRef = react.useRef(false);
2543
- const shouldPreventMountAnimationRef = react.useRef(open);
2544
- const shouldPreventActivityResumeAnimationRef = react.useRef(false);
2545
- const [forcePanelIdle, setForcePanelIdle] = react.useState(false);
2546
- const pendingTemporaryStyleRestoreRef = react.useRef(null);
2547
- const mergedPanelRef = useMergedRefs(externalRef, panelRef);
2548
- const latestOpenRef = useValueAsRef(open);
2549
- const runOnceCloseAnimationsFinish = useAnimationsFinished(panelRef);
2550
- const hidden = !open && !mounted;
2551
- const panelTransitionStatus = forcePanelIdle ? "idle" : transitionStatus;
2552
- const shouldPreventOpenAnimation = open && (shouldPreventMountAnimationRef.current || shouldPreventActivityResumeAnimationRef.current);
2553
- const renderedDimensions = !open && mounted && animationTypeRef.current === "css-animation" && dimensions.height === void 0 && dimensions.width === void 0 ? lastMeasuredDimensionsRef.current : dimensions;
2554
- const shouldPersistHiddenTransitionStyles = hiddenUntilFound && hidden && animationTypeRef.current !== "css-animation";
2555
- const setDimensions = useStableCallback((nextDimensions, shouldCacheMeasurement = true) => {
2556
- if (shouldCacheMeasurement) lastMeasuredDimensionsRef.current = nextDimensions;
2557
- setDimensionsUnwrapped(nextDimensions);
2558
- });
2559
- const restorePendingTemporaryStyle = useStableCallback(() => {
2560
- pendingTemporaryStyleRestoreRef.current?.();
2561
- pendingTemporaryStyleRestoreRef.current = null;
2562
- });
2563
- const setPendingTemporaryStyleRestore = useStableCallback((restore) => {
2564
- restorePendingTemporaryStyle();
2565
- pendingTemporaryStyleRestoreRef.current = () => {
2566
- pendingTemporaryStyleRestoreRef.current = null;
2567
- restore();
2568
- };
2569
- });
2570
- const markActivityResumeAnimationSuppressed = useStableCallback(() => {
2571
- if (open && mounted && animationTypeRef.current === "css-animation") shouldPreventActivityResumeAnimationRef.current = true;
2572
- });
2573
- useIsoLayoutEffect(() => {
2574
- if (!forcePanelIdle || transitionStatus === "starting") return;
2575
- setForcePanelIdle(false);
2576
- }, [forcePanelIdle, transitionStatus]);
2577
- react.useEffect(() => {
2578
- return () => {
2579
- markActivityResumeAnimationSuppressed();
2580
- restorePendingTemporaryStyle();
2581
- };
2582
- }, [markActivityResumeAnimationSuppressed, restorePendingTemporaryStyle]);
2306
+ //#region src/client/locale.ts
2307
+ /**
2308
+ * Panel copy, bilingual. Chinese is the authoring language; English is the
2309
+ * fallback the host's locale runtime consults after the active locale misses
2310
+ * a key (and the locale a browser naming neither shipped language lands on).
2311
+ *
2312
+ * The dictionaries register into the host's locale service (`ctx.locale`)
2313
+ * under this plugin's own namespace, so the panel follows the same language
2314
+ * switch as the rest of the UI. Templates interpolate `{name}` placeholders.
2315
+ *
2316
+ * tests/client/locale.spec.ts pins the two dictionaries to identical key sets
2317
+ * and checks every key the component looks up exists in both.
2318
+ */
2319
+ const LOCALE_NS = "capability-panel";
2320
+ const zh = {
2321
+ "state.loaded": "已加载",
2322
+ "state.pruned": "已截断",
2323
+ "state.evicted": "已挤出",
2324
+ "state.unloaded": "未加载",
2325
+ "blocked.count": "拦截 ×{count}",
2326
+ "action.enable": "开启 {name}",
2327
+ "action.disable": "关闭 {name}",
2328
+ "action.insert": "把 /{name} 填入输入框",
2329
+ "action.preview": "在侧边栏打开 {name} 的指令文件",
2330
+ "server.tools": "{count} 工具",
2331
+ "server.tool.one": "1 个工具",
2332
+ "server.unavailable": "无已注册工具",
2333
+ "server.unavailableHint": "宿主配置里声明了这个服务器,但它当前没有注册任何工具。原因无法从面板判定(服务未启动、正在重连、或本就没有工具都可能)。若它是个本地按需服务,先把程序开起来。",
2334
+ "action.reload": "重载 {name}",
2335
+ "action.reload.label": "重载",
2336
+ "action.reload.ing": "正在重载 {name}…",
2337
+ "action.reloadHint": "重新加载该服务器的插件实例(等同一次热重载):会断开并重连。对 stdio 类型的服务,这会重启其子进程。",
2338
+ "action.reload.failed": "重载 {name} 失败:{error}",
2339
+ "status.loading": "读取中…",
2340
+ "status.error": "读取失败:{error}(可尝试刷新页面;宿主改动需重启 dsh 后生效)",
2341
+ "empty.match": "无匹配项",
2342
+ "empty.skills": "无可用技能",
2343
+ "empty.mcp": "无 MCP 服务器",
2344
+ "empty.system": "无系统工具",
2345
+ "group.skills": "技能 ({shown}/{total})",
2346
+ "group.mcp": "MCP ({shown}/{total})",
2347
+ "group.system": "系统工具 ({shown}/{total})",
2348
+ "group.systemTools": "系统工具",
2349
+ "group.count": "{shown}/{total}",
2350
+ "tab.all": "全部",
2351
+ "tab.skills": "技能",
2352
+ "tab.mcp": "MCP",
2353
+ "tab.system": "工具",
2354
+ "tab.system.aria": "系统工具 {count}",
2355
+ "tabs.aria": "能力分区",
2356
+ "trigger.tooltip": "会话上下文:技能、MCP 与工具",
2357
+ "panel.aria": "会话上下文",
2358
+ "filter.placeholder": "筛选名称或描述…",
2359
+ "filter.aria": "筛选技能与工具",
2360
+ "filter.clear": "清空筛选",
2361
+ "filter.count": "匹配 {shown} / {total} 项",
2362
+ "footer.feedback": "反馈问题",
2363
+ "footer.feedbackHint": "在 GitHub 上打开能力面板的 issue 页",
2364
+ "footer.openSettings": "全局配置",
2365
+ "footer.openSettingsHint": "打开设置并进入「能力面板」页",
2366
+ "disclosure.expand": "展开 {subject} 的{detail}",
2367
+ "disclosure.collapse": "收起 {subject} 的{detail}",
2368
+ "disclosure.pinned": "{subject} 的{detail}(筛选时保持展开)",
2369
+ "detail.description": "描述",
2370
+ "detail.tools": "工具",
2371
+ "preset.nav": "能力面板",
2372
+ "preset.title": "能力面板",
2373
+ "preset.intro": "设置每个 Agent preset 的默认能力集合,之后新建或恢复的会话会继承它。输入框里的「会话上下文」只改当前会话,并随该会话在重启后恢复。",
2374
+ "preset.projectSkill": "当前项目",
2375
+ "preset.kindAria": "按类别筛选",
2376
+ "preset.readonly": "当前设置存储不可写;你可以查看工具,但无法保存微调。",
2377
+ "preset.choose": "Agent preset",
2378
+ "preset.empty": "没有可用的 Agent preset。",
2379
+ "preset.noTools": "这个 preset 没有可用能力。",
2380
+ "preset.reserved": "{name} 是保留的传输通道,不能关闭。",
2381
+ "preset.broken": "这个 preset 无法组装会话:{reason}。修好它之后才能列出工具。",
2382
+ "degraded.item": "⚠ 部分读取失败:{note}",
2383
+ "source.project-dsh": "项目 .dsh",
2384
+ "source.project-agents": "项目 agent",
2385
+ "source.runtime": "运行时",
2386
+ "source.user-dsh": "用户 .dsh",
2387
+ "source.user-agents": "用户 agent",
2388
+ "source.custom": "自定义",
2389
+ "source.bundled": "内置",
2390
+ "source.host": "全局",
2391
+ "source.preset": "预设",
2392
+ "source.openFolder": "在文件管理器中打开 {source}"
2393
+ };
2394
+ const en = {
2395
+ "state.loaded": "loaded",
2396
+ "state.pruned": "truncated",
2397
+ "state.evicted": "evicted",
2398
+ "state.unloaded": "not loaded",
2399
+ "blocked.count": "blocked ×{count}",
2400
+ "action.enable": "Enable {name}",
2401
+ "action.disable": "Disable {name}",
2402
+ "action.insert": "Insert /{name} into the composer",
2403
+ "action.preview": "Open the instruction file for {name} in the side panel",
2404
+ "server.tools": "{count} tools",
2405
+ "server.tool.one": "1 tool",
2406
+ "server.unavailable": "no tools registered",
2407
+ "server.unavailableHint": "This host declares the server, but it currently registers no tools. The panel cannot tell why (service not started, mid-reconnect, or genuinely tool-less are all possible). If it is a local on-demand service, start its program first.",
2408
+ "action.reload": "Reload {name}",
2409
+ "action.reload.label": "Reload",
2410
+ "action.reload.ing": "Reloading {name}…",
2411
+ "action.reloadHint": "Reload this server’s plugin instance (equivalent to one hot reload): it disconnects and reconnects. For a stdio service this restarts its child process.",
2412
+ "action.reload.failed": "Failed to reload {name}: {error}",
2413
+ "status.loading": "Loading…",
2414
+ "status.error": "Failed to load: {error} (try refreshing the page; host changes take effect after a dsh restart)",
2415
+ "empty.match": "No matches",
2416
+ "empty.skills": "No skills available",
2417
+ "empty.mcp": "No MCP servers",
2418
+ "empty.system": "No system tools",
2419
+ "group.skills": "Skills ({shown}/{total})",
2420
+ "group.mcp": "MCP ({shown}/{total})",
2421
+ "group.system": "System tools ({shown}/{total})",
2422
+ "group.systemTools": "System tools",
2423
+ "group.count": "{shown}/{total}",
2424
+ "tab.all": "All",
2425
+ "tab.skills": "Skills",
2426
+ "tab.mcp": "MCP",
2427
+ "tab.system": "Tools",
2428
+ "tab.system.aria": "System tools, {count}",
2429
+ "tabs.aria": "Capability sections",
2430
+ "trigger.tooltip": "Session context: skills, MCP & tools",
2431
+ "panel.aria": "Session context",
2432
+ "filter.placeholder": "Filter by name or description…",
2433
+ "filter.aria": "Filter skills and tools",
2434
+ "filter.clear": "Clear filter",
2435
+ "filter.count": "{shown} / {total} matched",
2436
+ "footer.feedback": "Report an issue",
2437
+ "footer.feedbackHint": "Open the capability panel’s issues on GitHub",
2438
+ "footer.openSettings": "Global settings",
2439
+ "footer.openSettingsHint": "Open Settings on the Capability Panel page",
2440
+ "disclosure.expand": "Expand {detail} for {subject}",
2441
+ "disclosure.collapse": "Collapse {detail} for {subject}",
2442
+ "disclosure.pinned": "{detail} for {subject} (kept open while filtering)",
2443
+ "detail.description": "description",
2444
+ "detail.tools": "tools",
2445
+ "preset.nav": "Capability Panel",
2446
+ "preset.title": "Capability Panel",
2447
+ "preset.intro": "Choose the default capabilities each agent preset starts from; sessions created or resumed afterward inherit it. The composer's Session context changes only the current session, and stays with it across restarts.",
2448
+ "preset.projectSkill": "this project",
2449
+ "preset.kindAria": "Filter by category",
2450
+ "preset.readonly": "Settings storage is read-only. You can inspect tools, but changes cannot be saved.",
2451
+ "preset.choose": "Agent preset",
2452
+ "preset.empty": "No agent presets are available.",
2453
+ "preset.noTools": "This preset exposes no capabilities.",
2454
+ "preset.reserved": "{name} is a reserved transport and cannot be disabled.",
2455
+ "preset.broken": "This preset cannot compose a session: {reason}. Fix it before its tools can be listed.",
2456
+ "degraded.item": "⚠ Partial read failed: {note}",
2457
+ "source.project-dsh": "project .dsh",
2458
+ "source.project-agents": "project agent",
2459
+ "source.runtime": "runtime",
2460
+ "source.user-dsh": "user .dsh",
2461
+ "source.user-agents": "user agent",
2462
+ "source.custom": "custom",
2463
+ "source.bundled": "bundled",
2464
+ "source.host": "global",
2465
+ "source.preset": "preset",
2466
+ "source.openFolder": "Open {source} in file manager"
2467
+ };
2468
+ /**
2469
+ * Register both dictionaries as one effect: the single-locale form is the
2470
+ * documented entry for namespaces outside the host's compile-time merge
2471
+ * table, and the returned disposers release both on unload.
2472
+ */
2473
+ function registerLocale(locale) {
2474
+ const disposeZh = locale.register(LOCALE_NS, "zh", zh);
2475
+ const disposeEn = locale.register(LOCALE_NS, "en", en);
2476
+ return () => {
2477
+ disposeZh();
2478
+ disposeEn();
2479
+ };
2480
+ }
2481
+
2482
+ //#endregion
2483
+ //#region src/client/styles.ts
2484
+ const TOK = {
2485
+ textPrimary: "var(--dsw-alias-label-primary, #0f1115)",
2486
+ textSecondary: "var(--dsw-alias-label-secondary, #61666b)",
2487
+ textTertiary: "var(--dsw-alias-label-tertiary, #81858c)",
2488
+ border: "var(--dsw-alias-border-l1, rgba(0,0,0,.04))",
2489
+ borderStrong: "var(--dsw-alias-border-l2, rgba(0,0,0,.1))",
2490
+ switchOn: "var(--dsw-alias-state-business-primary, #4176e6)",
2491
+ switchOff: "var(--dsw-alias-border-l2, rgba(0,0,0,.1))",
2492
+ switchThumb: "var(--dsw-alias-bg-layer-1, #ffffff)",
2493
+ switchEase: "var(--ds-ease-in-out, cubic-bezier(.4, 0, .2, 1))",
2494
+ menuBg: "var(--dsw-specific-menu, #ffffff)",
2495
+ menuBorder: "var(--dsw-alias-border-inverted, rgba(0,0,0,.1))",
2496
+ menuShadow: "var(--dsw-shadow-lv3, 0 12px 32px rgba(0,0,0,.22))",
2497
+ menuBlur: "var(--dsw-menu-backdrop-filter, none)",
2498
+ bgBase: "var(--dsw-alias-bg-base, #ffffff)",
2499
+ fontFamily: "var(--dsw-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", \"Helvetica Neue\", Helvetica, Arial, sans-serif)",
2500
+ success: "var(--dsw-alias-state-success-primary, #22c55e)",
2501
+ warn: "var(--dsw-alias-state-warn-primary, #f59e0b)",
2502
+ error: "var(--dsw-alias-state-error-primary, #ec1313)",
2503
+ info: "var(--dsw-alias-state-business-primary, #4176e6)"
2504
+ };
2505
+ const PANEL_CSS = [
2506
+ ".ci-trigger:focus-visible,.ci-switch:focus-visible,.ci-iconbtn:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;border-radius:999px}",
2507
+ ".ci-disclosure-trigger:focus-visible,.ci-server-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;border-radius:4px}",
2508
+ ".ci-tab:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px;border-radius:6px}",
2509
+ ".ci-trigger:hover,.ci-iconbtn:hover,.ci-server-trigger:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
2510
+ ".ci-switch:hover:not(:disabled){filter:brightness(1.12)}",
2511
+ ".ci-row-head{display:flex;align-items:center;gap:8px;padding:6px 8px;margin:0 -8px;border-radius:8px}",
2512
+ ".ci-row-head:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
2513
+ ".ci-row-head .ci-send{opacity:0;transition:opacity .12s}",
2514
+ ".ci-row-head:hover .ci-send,.ci-row-head:focus-within .ci-send{opacity:1}",
2515
+ ".ci-filter:focus{border-color:var(--dsw-alias-state-business-primary,#4176e6)}",
2516
+ ".ci-filter:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:0}",
2517
+ ".ci-filter::placeholder{color:var(--dsw-alias-label-tertiary,#81858c)}",
2518
+ ".ci-panel{transform-origin:var(--transform-origin);transition:opacity .14s var(--ds-ease-in-out,ease),transform .14s var(--ds-ease-in-out,ease)}",
2519
+ ".ci-panel[data-starting-style],.ci-panel[data-ending-style]{opacity:0;transform:scale(.96) translateY(4px)}",
2520
+ ".ci-collapse{height:var(--collapsible-panel-height);transition:height .14s var(--ds-ease-in-out,ease);overflow:hidden}",
2521
+ ".ci-collapse[data-starting-style],.ci-collapse[data-ending-style]{height:0}",
2522
+ ".ci-toolrow{content-visibility:auto;contain-intrinsic-size:auto 30px}",
2523
+ ".ci-disclosure-trigger{min-width:0;display:flex;align-items:center;gap:6px;flex:1 1 auto;padding:0;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}",
2524
+ ".ci-disclosure-trigger:disabled,.ci-server-trigger:disabled{cursor:default}",
2525
+ ".ci-disclosure-trigger:hover .ci-name{color:var(--dsw-alias-label-primary,#0f1115)}",
2526
+ ".ci-description{padding:3px 0 0 24px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858c);word-break:break-word}",
2527
+ ".ci-chevron{display:grid;place-items:center;width:18px;height:18px;flex:none;color:var(--dsw-alias-label-tertiary,#81858c);border-radius:4px}",
2528
+ ".ci-chevron svg{transition:transform .12s var(--ds-ease-in-out,ease)}",
2529
+ ".ci-leading{position:relative;display:grid;place-items:center;width:18px;height:18px;flex:none;color:var(--dsw-alias-label-tertiary,#81858c)}",
2530
+ ".ci-leading>.ci-row-icon{display:grid;place-items:center;opacity:1;transition:opacity .12s var(--ds-ease-in-out,ease)}",
2531
+ ".ci-leading>.ci-chevron-hover{position:absolute;inset:0;margin:auto;display:grid;place-items:center;opacity:0;transition:opacity .12s var(--ds-ease-in-out,ease)}",
2532
+ ".ci-row-head:hover .ci-leading>.ci-row-icon,.ci-row-head:focus-within .ci-leading>.ci-row-icon{opacity:0}",
2533
+ ".ci-row-head:hover .ci-leading>.ci-chevron-hover,.ci-row-head:focus-within .ci-leading>.ci-chevron-hover{opacity:1}",
2534
+ ".ci-preset-part-trigger[aria-expanded=\"true\"] .ci-chevron svg{transform:rotate(90deg)}",
2535
+ ".ci-tabs{display:flex;gap:2px;padding:2px;border-radius:8px;background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
2536
+ ".ci-tab{flex:1;height:24px;border:none;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary,#61666b);font:inherit;font-size:12px;line-height:1;cursor:pointer;font-variant-numeric:tabular-nums;padding:0 4px}",
2537
+ ".ci-tab:hover{color:var(--dsw-alias-label-primary,#0f1115)}",
2538
+ ".ci-tab[data-active]{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#0f1115);box-shadow:var(--dsw-elevation-soft,0 1px 2px rgba(0,0,0,.08))}",
2539
+ ".ci-preset-section{width:100%;max-width:760px;color:var(--dsw-alias-label-primary,#0f1115);display:flex;flex-direction:column;gap:14px}",
2540
+ ".ci-settings-title{margin:0;color:var(--dsw-alias-label-primary,#0f1115);font-size:18px;font-weight:600;line-height:26px}",
2541
+ ".ci-settings-intro,.ci-settings-description,.ci-settings-note{margin:0;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary,#81858c)}",
2542
+ ".ci-settings-note{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1));border-radius:8px}",
2543
+ ".ci-preset-toolbar{display:flex;gap:10px;align-items:center;margin:0}",
2544
+ ".ci-search{position:relative;flex:1 1 auto;min-width:180px;display:flex;align-items:center;color:var(--dsw-alias-label-tertiary,#81858c)}",
2545
+ ".ci-search>svg{position:absolute;left:12px;pointer-events:none}",
2546
+ ".ci-preset-filter{width:100%;height:36px;box-sizing:border-box;padding:0 34px 0 36px;border:.5px solid var(--dsw-alias-border-l4,rgba(0,0,0,.16));border-radius:var(--dsw-radius-md,12px);background-color:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-size:13px;font-weight:400;outline:none}",
2547
+ ".ci-preset-filter:focus-visible{border-color:var(--dsw-alias-state-business-primary,#4176e6);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-state-business-primary,#4176e6) 18%,transparent)}",
2548
+ ".ci-preset-part{display:flex;flex-direction:column;gap:10px;margin:0;padding:14px 0 0;border-top:.5px solid var(--dsw-alias-border-l2,rgba(0,0,0,.1))}",
2549
+ ".ci-preset-part:first-of-type{border-top:0;padding-top:0}",
2550
+ ".ci-preset-part-trigger{display:flex;align-items:center;gap:8px;min-height:32px;padding:0;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer}",
2551
+ ".ci-preset-part-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px;border-radius:4px}",
2552
+ ".ci-preset-part-title{margin:0;font-size:14px;font-weight:400;line-height:22px;color:var(--dsw-alias-label-primary,#0f1115)}",
2553
+ ".ci-preset-part-sub{margin:-4px 0 0 26px;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary,#81858c);font-variant-numeric:tabular-nums}",
2554
+ ".ci-preset-badge{display:inline-block;margin-left:6px;padding:1px 6px;line-height:1.5;border-radius:999px;font-size:11px;font-weight:500;vertical-align:middle;background-color:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.05));color:var(--dsw-alias-label-tertiary,#81858c)}",
2555
+ ".ci-preset-group{padding:0}",
2556
+ ".ci-preset-server-trigger{display:flex;align-items:center;gap:8px;flex:1;min-width:0;background:none;border:none;padding:0;text-align:left;font:inherit;color:inherit;cursor:pointer}",
2557
+ ".ci-preset-server-trigger:disabled{cursor:default}",
2558
+ ".ci-preset-group .ci-preset-tool-list{margin:0;padding-left:26px}",
2559
+ ".ci-preset-picker-trigger{height:36px;display:inline-flex;align-items:center;gap:8px;padding:0 14px;border:none;border-radius:var(--dsw-radius-md,12px);background:var(--dsw-alias-bg-module-platform,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#0f1115);font:inherit;font-size:14px;font-weight:400;line-height:22px;cursor:pointer;outline:none;max-width:280px;flex:none;white-space:nowrap}",
2560
+ ".ci-preset-picker-trigger:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06))}",
2561
+ ".ci-preset-picker-trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px}",
2562
+ ".ci-preset-picker-name{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}",
2563
+ ".ci-preset-picker-chevron{color:var(--dsw-alias-label-tertiary,#81858c);flex:none;display:inline-grid;place-items:center;transition:transform .12s}",
2564
+ ".ci-preset-picker-chevron-open{transform:rotate(180deg)}",
2565
+ ".ci-settings-subtitle{margin:0 0 6px;color:var(--dsw-alias-label-primary,#0f1115);font-size:14px;line-height:22px}",
2566
+ ".ci-preset-tool-list{list-style:none;margin:0;padding:0}",
2567
+ ".ci-preset-tool-row{display:flex;align-items:center;gap:16px}",
2568
+ ".ci-preset-tool-copy{display:grid;min-width:0;flex:1}",
2569
+ ".ci-preset-tool-name{color:var(--dsw-alias-label-primary,#0f1115);font-weight:600;overflow-wrap:anywhere}",
2570
+ ".ci-preset-tool-description{color:var(--dsw-alias-label-tertiary,#81858c);line-height:18px;overflow-wrap:anywhere}",
2571
+ ".ci-preset-item{list-style:none}",
2572
+ ".ci-preset-disclosure{display:block}",
2573
+ ".ci-preset-spacer{width:18px;flex:none}",
2574
+ ".ci-preset-detail{padding:0 0 10px 24px;color:var(--dsw-alias-label-tertiary,#81858c);line-height:18px;overflow-wrap:anywhere}",
2575
+ ".ci-preset-kinds{margin:0}",
2576
+ ".ci-preset-kinds .ci-tabs{display:inline-flex}",
2577
+ ".ci-preset-kinds .ci-tab{flex:0 0 auto;padding:0 12px}",
2578
+ ".ci-source-header:hover .ci-folder-icon{opacity:1 !important}",
2579
+ ".ci-reconnect{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.14));background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-secondary,#61666b);border-radius:8px;padding:3px 9px;font-size:12px;line-height:1.4;cursor:pointer;font-family:inherit;flex:none}",
2580
+ ".ci-reconnect:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,rgba(38,49,72,.06));color:var(--dsw-alias-label-primary,#0f1115)}",
2581
+ ".ci-reconnect:disabled{opacity:.7;cursor:default}",
2582
+ ".ci-reconnect:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:1px}",
2583
+ ".ci-reconnect-glyph{display:inline-grid;place-items:center;width:12px;height:12px}",
2584
+ ".ci-reconnect-busy .ci-reconnect-glyph{animation:ci-reconnect-spin .8s linear infinite}",
2585
+ "@keyframes ci-reconnect-spin{to{transform:rotate(360deg)}}",
2586
+ "@media (prefers-reduced-motion: reduce){.ci-reconnect-busy .ci-reconnect-glyph{animation:none}}",
2587
+ ".ci-source-divider{list-style:none}",
2588
+ ".ci-feedback-link{display:inline-flex;align-items:center;gap:4px;color:var(--dsw-alias-label-tertiary,#8a8f98);font-size:12px;line-height:18px;text-decoration:none;cursor:pointer}",
2589
+ ".ci-feedback-link:hover{color:var(--dsw-alias-label-primary,#0f1115);text-decoration:underline}",
2590
+ ".ci-feedback-link:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4176e6);outline-offset:2px;border-radius:3px}",
2591
+ ".ci-feedback-icon{display:inline-grid;place-items:center;flex:none}",
2592
+ ".ci-settings-link{border:0;background:none;padding:0;font-family:inherit}",
2593
+ "@media (prefers-reduced-motion: reduce){.ci-thumb,.ci-panel,.ci-collapse,.ci-chevron svg{transition:none !important}}"
2594
+ ].join("\n");
2595
+
2596
+ //#endregion
2597
+ //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/visuallyHidden.mjs
2598
+ const visuallyHiddenBase = {
2599
+ clipPath: "inset(50%)",
2600
+ overflow: "hidden",
2601
+ whiteSpace: "nowrap",
2602
+ border: 0,
2603
+ padding: 0,
2604
+ width: 1,
2605
+ height: 1,
2606
+ margin: -1
2607
+ };
2608
+ const visuallyHidden = {
2609
+ ...visuallyHiddenBase,
2610
+ position: "fixed",
2611
+ top: 0,
2612
+ left: 0
2613
+ };
2614
+ const visuallyHiddenInput = {
2615
+ ...visuallyHiddenBase,
2616
+ position: "absolute"
2617
+ };
2618
+
2619
+ //#endregion
2620
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/root/SwitchRootContext.mjs
2621
+ const SwitchRootContext = /* @__PURE__ */ react.createContext(void 0);
2622
+ function useSwitchRootContext() {
2623
+ const context = react.useContext(SwitchRootContext);
2624
+ if (context === void 0) throw new Error(formatErrorMessage_default(63));
2625
+ return context;
2626
+ }
2627
+
2628
+ //#endregion
2629
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/field-constants/constants.mjs
2630
+ const DEFAULT_VALIDITY_STATE = {
2631
+ badInput: false,
2632
+ customError: false,
2633
+ patternMismatch: false,
2634
+ rangeOverflow: false,
2635
+ rangeUnderflow: false,
2636
+ stepMismatch: false,
2637
+ tooLong: false,
2638
+ tooShort: false,
2639
+ typeMismatch: false,
2640
+ valid: null,
2641
+ valueMissing: false
2642
+ };
2643
+ const DEFAULT_FIELD_STATE_ATTRIBUTES = {
2644
+ valid: null,
2645
+ touched: false,
2646
+ dirty: false,
2647
+ filled: false,
2648
+ focused: false
2649
+ };
2650
+ const DEFAULT_FIELD_ROOT_STATE = {
2651
+ disabled: false,
2652
+ ...DEFAULT_FIELD_STATE_ATTRIBUTES
2653
+ };
2654
+ const fieldValidityMapping = { valid(value) {
2655
+ if (value === null) return null;
2656
+ if (value) return { "data-valid": "" };
2657
+ return { "data-invalid": "" };
2658
+ } };
2659
+
2660
+ //#endregion
2661
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/stateAttributesMapping.mjs
2662
+ const stateAttributesMapping$1 = {
2663
+ ...fieldValidityMapping,
2664
+ checked(value) {
2665
+ if (value) return { "data-checked": "" };
2666
+ return { "data-unchecked": "" };
2667
+ }
2668
+ };
2669
+
2670
+ //#endregion
2671
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/field-root-context/FieldRootContext.mjs
2672
+ const DEFAULT_FIELD_ROOT_CONTEXT = {
2673
+ invalid: void 0,
2674
+ name: void 0,
2675
+ validityData: {
2676
+ state: DEFAULT_VALIDITY_STATE,
2677
+ errors: [],
2678
+ error: "",
2679
+ value: "",
2680
+ initialValue: null
2681
+ },
2682
+ setValidityData: NOOP,
2683
+ disabled: void 0,
2684
+ setTouched: NOOP,
2685
+ setDirty: NOOP,
2686
+ setFilled: NOOP,
2687
+ setFocused: NOOP,
2688
+ validationMode: "onSubmit",
2689
+ shouldValidateOnChange: () => false,
2690
+ state: DEFAULT_FIELD_ROOT_STATE,
2691
+ registerFieldControl: NOOP,
2692
+ validation: {
2693
+ getValidationProps: (_disabled, props = EMPTY_OBJECT) => props,
2694
+ inputRef: { current: null },
2695
+ registeredInputs: /* @__PURE__ */ new Map(),
2696
+ registerInput: NOOP,
2697
+ getInputControl: () => null,
2698
+ commit: async () => {},
2699
+ change: NOOP
2700
+ }
2701
+ };
2702
+ const FieldRootContext = /* @__PURE__ */ react.createContext(DEFAULT_FIELD_ROOT_CONTEXT);
2703
+ function useFieldRootContext(optional = true) {
2704
+ const context = react.useContext(FieldRootContext);
2705
+ if (context.setValidityData === NOOP && !optional) throw new Error(formatErrorMessage_default(28));
2706
+ return context;
2707
+ }
2708
+
2709
+ //#endregion
2710
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/field-register-control/useRegisterFieldControl.mjs
2711
+ function useRegisterFieldControl(controlRef, id, value, getFormValueOverride, enabled = true, name) {
2712
+ const { registerFieldControl } = useFieldRootContext();
2713
+ const sourceRef = useRefWithInit(() => Symbol());
2583
2714
  useIsoLayoutEffect(() => {
2584
- const panel = panelRef.current;
2585
- if (!panel) return;
2586
- if (!open && pendingTemporaryStyleRestoreRef.current) restorePendingTemporaryStyle();
2587
- const animationType = getAnimationType(panel, shouldPreventOpenAnimation);
2588
- animationTypeRef.current = animationType;
2589
- if (open && transitionStatus === "idle" && shouldPreventMountAnimationRef.current && animationType === "css-animation") {
2590
- lastMeasuredDimensionsRef.current = getDimensions$1(panel);
2591
- return;
2592
- }
2593
- if (open && transitionStatus === "starting") {
2594
- const skipNextOpen = shouldSkipNextOpenRef.current;
2595
- shouldSkipNextOpenRef.current = false;
2596
- if (animationType === "none") {
2597
- setDimensions(getDimensions$1(panel));
2598
- setForcePanelIdle(true);
2599
- return;
2600
- }
2601
- if (animationType === "css-transition") {
2602
- const restoreLayoutStyles = resetLayoutStyles(panel);
2603
- setDimensions(getDimensions$1(panel));
2604
- if (!skipNextOpen) return restoreLayoutStyles;
2605
- setPendingTemporaryStyleRestore(setTemporaryStyle(panel, "transition-duration", "0s"));
2606
- setForcePanelIdle(true);
2607
- return restoreLayoutStyles;
2608
- }
2609
- setDimensions(getDimensions$1(panel));
2610
- const restoreAnimationName = setTemporaryStyle(panel, "animation-name", "none");
2611
- if (!skipNextOpen) {
2612
- restoreAnimationName();
2613
- return;
2614
- }
2615
- const restoreAnimationDuration = setTemporaryStyle(panel, "animation-duration", "0s");
2616
- restoreAnimationName();
2617
- setPendingTemporaryStyleRestore(restoreAnimationDuration);
2618
- setForcePanelIdle(true);
2619
- return;
2620
- }
2621
- if (!open && mounted && (transitionStatus === "idle" || transitionStatus === "starting")) {
2622
- shouldPreventMountAnimationRef.current = false;
2623
- shouldPreventActivityResumeAnimationRef.current = false;
2624
- if (animationType === "none") {
2625
- setDimensions(EMPTY_DIMENSIONS, false);
2626
- setMounted(false);
2627
- return;
2628
- }
2629
- setDimensions(getDimensions$1(panel));
2630
- return;
2631
- }
2632
- if (transitionStatus !== "ending") return;
2633
- if (animationType === "none") {
2634
- setMounted(false);
2635
- return;
2636
- }
2637
- const nextDimensions = getDimensions$1(panel);
2638
- if (!(nextDimensions.height > 0 || nextDimensions.width > 0)) {
2639
- setMounted(false);
2715
+ const source = sourceRef.current;
2716
+ if (!enabled) {
2717
+ registerFieldControl(source, void 0);
2640
2718
  return;
2641
2719
  }
2642
- setDimensions(nextDimensions);
2643
- if (animationType === "css-animation") setTemporaryStyle(panel, "animation-name", "none")();
2720
+ registerFieldControl(source, {
2721
+ controlRef,
2722
+ getValue: getFormValueOverride,
2723
+ id,
2724
+ name,
2725
+ value
2726
+ });
2644
2727
  }, [
2645
- mounted,
2646
- open,
2647
- restorePendingTemporaryStyle,
2648
- setDimensions,
2649
- setMounted,
2650
- setPendingTemporaryStyleRestore,
2651
- shouldPreventOpenAnimation,
2652
- transitionStatus
2728
+ controlRef,
2729
+ enabled,
2730
+ getFormValueOverride,
2731
+ id,
2732
+ name,
2733
+ registerFieldControl,
2734
+ sourceRef,
2735
+ value
2653
2736
  ]);
2654
- useOpenChangeComplete({
2655
- enabled: open && mounted && panelTransitionStatus === "idle",
2656
- open: true,
2657
- ref: panelRef,
2658
- onComplete() {
2659
- if (!open) return;
2660
- setDimensions(EMPTY_DIMENSIONS, false);
2737
+ useIsoLayoutEffect(() => {
2738
+ const source = sourceRef.current;
2739
+ return () => {
2740
+ registerFieldControl(source, void 0);
2741
+ };
2742
+ }, [registerFieldControl, sourceRef]);
2743
+ }
2744
+
2745
+ //#endregion
2746
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/form-context/FormContext.mjs
2747
+ const FormContext = /* @__PURE__ */ react.createContext({
2748
+ elementRef: { current: null },
2749
+ formRef: { current: { fields: /* @__PURE__ */ new Map() } },
2750
+ errors: {},
2751
+ clearErrors: NOOP,
2752
+ validationMode: "onSubmit",
2753
+ submitAttemptedRef: { current: false }
2754
+ });
2755
+ function useFormContext() {
2756
+ return react.useContext(FormContext);
2757
+ }
2758
+
2759
+ //#endregion
2760
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/labelable-provider/LabelableContext.mjs
2761
+ /**
2762
+ * A context for providing [labelable elements](https://html.spec.whatwg.org/multipage/forms.html#category-label)\
2763
+ * with an accessible name (label) and description.
2764
+ */
2765
+ const LabelableContext = /* @__PURE__ */ react.createContext({
2766
+ controlId: void 0,
2767
+ registerControlId: NOOP,
2768
+ labelId: void 0,
2769
+ setLabelId: NOOP,
2770
+ messageIds: [],
2771
+ setMessageIds: NOOP,
2772
+ getDescriptionProps: (externalProps) => externalProps
2773
+ });
2774
+ function useLabelableContext() {
2775
+ return react.useContext(LabelableContext);
2776
+ }
2777
+
2778
+ //#endregion
2779
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/labelable-provider/useAriaLabelledBy.mjs
2780
+ function useAriaLabelledBy(explicitAriaLabelledBy, labelId, labelSourceRef, enableFallback = true, labelSourceId) {
2781
+ const [fallbackAriaLabelledBy, setFallbackAriaLabelledBy] = react.useState();
2782
+ const generatedLabelId = useBaseUiId(labelSourceId ? `${labelSourceId}-label` : void 0);
2783
+ const ariaLabelledBy = explicitAriaLabelledBy ?? labelId ?? fallbackAriaLabelledBy;
2784
+ useIsoLayoutEffect(() => {
2785
+ const nextAriaLabelledBy = explicitAriaLabelledBy || labelId || !enableFallback ? void 0 : getAriaLabelledBy(labelSourceRef.current, generatedLabelId);
2786
+ if (fallbackAriaLabelledBy !== nextAriaLabelledBy) setFallbackAriaLabelledBy(nextAriaLabelledBy);
2787
+ });
2788
+ return ariaLabelledBy;
2789
+ }
2790
+ function getAriaLabelledBy(labelSource, generatedLabelId) {
2791
+ const label = findAssociatedLabel(labelSource);
2792
+ if (!label) return;
2793
+ if (!label.id && generatedLabelId) label.id = generatedLabelId;
2794
+ return label.id || void 0;
2795
+ }
2796
+ function findAssociatedLabel(labelSource) {
2797
+ if (!labelSource) return;
2798
+ const parent = labelSource.parentElement;
2799
+ if (parent && parent.tagName === "LABEL") return parent;
2800
+ const controlId = labelSource.id;
2801
+ if (controlId) {
2802
+ const nextSibling = labelSource.nextElementSibling;
2803
+ if (nextSibling && nextSibling.htmlFor === controlId) return nextSibling;
2804
+ }
2805
+ const labels = labelSource.labels;
2806
+ return labels && labels[0];
2807
+ }
2808
+
2809
+ //#endregion
2810
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/labelable-provider/useLabelableId.mjs
2811
+ function useLabelableId(params = {}) {
2812
+ const { id, implicit = false, controlRef } = params;
2813
+ const { controlId, registerControlId } = useLabelableContext();
2814
+ const defaultId = useBaseUiId(id);
2815
+ const controlIdForEffect = implicit ? controlId : void 0;
2816
+ const controlSourceRef = useRefWithInit(() => Symbol());
2817
+ const hasRegisteredRef = react.useRef(false);
2818
+ const hadExplicitIdRef = react.useRef(id != null);
2819
+ const unregisterControlId = useStableCallback(() => {
2820
+ if (!hasRegisteredRef.current || registerControlId === NOOP) return;
2821
+ hasRegisteredRef.current = false;
2822
+ registerControlId(controlSourceRef.current, void 0);
2823
+ });
2824
+ useIsoLayoutEffect(() => {
2825
+ if (registerControlId === NOOP) return;
2826
+ let nextId;
2827
+ if (implicit) {
2828
+ const elem = controlRef?.current;
2829
+ if (isElement(elem) && elem.closest("label") != null) nextId = id ?? null;
2830
+ else nextId = controlIdForEffect ?? defaultId;
2831
+ } else if (id != null) {
2832
+ hadExplicitIdRef.current = true;
2833
+ nextId = id;
2834
+ } else if (hadExplicitIdRef.current) nextId = defaultId;
2835
+ else {
2836
+ unregisterControlId();
2837
+ return;
2661
2838
  }
2662
- });
2663
- react.useEffect(() => {
2664
- if (open || !mounted || panelTransitionStatus !== "ending") return;
2665
- if (!panelRef.current) return;
2666
- const abortController = new AbortController();
2667
- let endingStyleFrame = -1;
2668
- function handleComplete() {
2669
- if (latestOpenRef.current) return;
2670
- setMounted(false);
2671
- setDimensions(EMPTY_DIMENSIONS, false);
2839
+ if (nextId === void 0) {
2840
+ unregisterControlId();
2841
+ return;
2672
2842
  }
2673
- endingStyleFrame = AnimationFrame.request(() => {
2674
- runOnceCloseAnimationsFinish(handleComplete, abortController.signal);
2675
- });
2676
- return () => {
2677
- AnimationFrame.cancel(endingStyleFrame);
2678
- abortController.abort();
2679
- };
2843
+ hasRegisteredRef.current = true;
2844
+ registerControlId(controlSourceRef.current, nextId);
2680
2845
  }, [
2681
- latestOpenRef,
2682
- mounted,
2683
- open,
2684
- panelTransitionStatus,
2685
- runOnceCloseAnimationsFinish,
2686
- setDimensions,
2687
- setMounted
2846
+ id,
2847
+ controlRef,
2848
+ controlIdForEffect,
2849
+ registerControlId,
2850
+ implicit,
2851
+ defaultId,
2852
+ controlSourceRef,
2853
+ unregisterControlId
2688
2854
  ]);
2689
- useIsoLayoutEffect(() => {
2690
- const panel = panelRef.current;
2691
- if (!panel || !hiddenUntilFound || !hidden) return;
2692
- panel.setAttribute("hidden", "until-found");
2693
- }, [hidden, hiddenUntilFound]);
2694
- react.useEffect(function registerBeforeMatchListener() {
2695
- const panel = panelRef.current;
2696
- if (!panel) return;
2697
- function handleBeforeMatch(event) {
2698
- const eventDetails = createChangeEventDetails(none, event);
2699
- onOpenChange(true, eventDetails);
2700
- if (eventDetails.isCanceled) return;
2701
- shouldSkipNextOpenRef.current = true;
2702
- setOpen(true);
2703
- }
2704
- return addEventListener(panel, "beforematch", handleBeforeMatch);
2705
- }, [onOpenChange, setOpen]);
2706
- const shouldRender = keepMounted || hiddenUntilFound || mounted || open;
2707
- return {
2708
- height: renderedDimensions.height,
2709
- props: {
2710
- ...shouldPersistHiddenTransitionStyles ? { [CollapsiblePanelDataAttributes.startingStyle]: "" } : void 0,
2711
- hidden,
2712
- id: idParam
2713
- },
2714
- ref: mergedPanelRef,
2715
- shouldPreventOpenAnimation,
2716
- shouldRender,
2717
- transitionStatus: panelTransitionStatus,
2718
- width: renderedDimensions.width
2719
- };
2720
- }
2721
- function getDimensions$1(element) {
2722
- return {
2723
- height: element.scrollHeight,
2724
- width: element.scrollWidth
2725
- };
2726
- }
2727
- function getAnimationType(element, hasSuppressedMountAnimation) {
2728
- const panelStyles = getWindow(element).getComputedStyle(element);
2729
- const hasAnimation = (panelStyles.animationName.split(",").map((name) => name.trim()).some((name) => name !== "" && name !== "none") || hasSuppressedMountAnimation) && hasNonZeroDuration(panelStyles.animationDuration);
2730
- const hasTransition = hasNonZeroDuration(panelStyles.transitionDuration);
2731
- if (hasAnimation && hasTransition) return "css-transition";
2732
- if (hasTransition) return "css-transition";
2733
- if (hasAnimation) return "css-animation";
2734
- return "none";
2855
+ react.useEffect(() => {
2856
+ return unregisterControlId;
2857
+ }, [unregisterControlId]);
2858
+ return controlId ?? defaultId;
2735
2859
  }
2736
- function hasNonZeroDuration(value) {
2737
- return value.split(",").map((part) => part.trim()).some((part) => part !== "" && Number.parseFloat(part) > 0);
2860
+
2861
+ //#endregion
2862
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/internals/useValueChanged.mjs
2863
+ function useValueChanged(value, onChange) {
2864
+ const valueRef = react.useRef(value);
2865
+ const onChangeCallback = useStableCallback(onChange);
2866
+ useIsoLayoutEffect(() => {
2867
+ if (valueRef.current !== value) onChangeCallback(valueRef.current);
2868
+ valueRef.current = value;
2869
+ }, [value, onChangeCallback]);
2738
2870
  }
2739
- /**
2740
- * Temporarily overrides an inline style property and returns a cleanup that
2741
- * restores the previous inline value and priority.
2742
- * @param element - The element whose inline style should be updated.
2743
- * @param property - The CSS property name to override.
2744
- * @param value - The temporary value to assign.
2745
- * @returns A cleanup function that restores the original inline style state.
2746
- */
2747
- function setTemporaryStyle(element, property, value) {
2748
- const previousValue = element.style.getPropertyValue(property);
2749
- const previousPriority = element.style.getPropertyPriority(property);
2750
- element.style.setProperty(property, value);
2751
- return () => {
2752
- if (previousValue === "") {
2753
- element.style.removeProperty(property);
2754
- return;
2871
+
2872
+ //#endregion
2873
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/root/SwitchRoot.mjs
2874
+ const SwitchRoot = /* @__PURE__ */ react.forwardRef(function SwitchRoot$1(componentProps, forwardedRef) {
2875
+ const { checked: checkedProp, className, defaultChecked, "aria-labelledby": ariaLabelledByProp, form, id: idProp, inputRef: externalInputRef, name: nameProp, nativeButton = false, onCheckedChange, readOnly = false, required = false, disabled: disabledProp = false, render, uncheckedValue, value, style,...elementProps } = componentProps;
2876
+ const { clearErrors } = useFormContext();
2877
+ const { state: fieldState, setTouched, setDirty, validityData, setFilled, setFocused, validationMode, disabled: fieldDisabled, name: fieldName, validation } = useFieldRootContext();
2878
+ const { labelId } = useLabelableContext();
2879
+ const disabled$1 = fieldDisabled || disabledProp;
2880
+ const name = fieldName ?? nameProp;
2881
+ const inputRef = react.useRef(null);
2882
+ const handleInputRef = useMergedRefs(inputRef, externalInputRef, validation.inputRef);
2883
+ const switchRef = react.useRef(null);
2884
+ const id = useBaseUiId();
2885
+ const controlId = useLabelableId({
2886
+ id: idProp,
2887
+ implicit: false,
2888
+ controlRef: switchRef
2889
+ });
2890
+ const hiddenInputId = nativeButton ? void 0 : controlId;
2891
+ const [checked, setCheckedState] = useControlled({
2892
+ controlled: checkedProp,
2893
+ default: Boolean(defaultChecked),
2894
+ name: "Switch",
2895
+ state: "checked"
2896
+ });
2897
+ useRegisterFieldControl(switchRef, id, checked, void 0, !disabled$1, nameProp);
2898
+ useIsoLayoutEffect(() => {
2899
+ if (inputRef.current) setFilled(inputRef.current.checked);
2900
+ }, [setFilled]);
2901
+ useValueChanged(checked, () => {
2902
+ clearErrors(name);
2903
+ setDirty(checked !== validityData.initialValue);
2904
+ setFilled(checked);
2905
+ validation.change(checked);
2906
+ });
2907
+ const { getButtonProps, buttonRef } = useButton({
2908
+ disabled: disabled$1,
2909
+ native: nativeButton
2910
+ });
2911
+ const ariaLabelledBy = useAriaLabelledBy(ariaLabelledByProp, labelId, inputRef, !nativeButton, hiddenInputId);
2912
+ const rootProps = {
2913
+ id: nativeButton ? controlId : id,
2914
+ role: "switch",
2915
+ "aria-checked": checked,
2916
+ "aria-readonly": readOnly || void 0,
2917
+ "aria-required": required || void 0,
2918
+ "aria-labelledby": ariaLabelledBy,
2919
+ onFocus() {
2920
+ if (!disabled$1) setFocused(true);
2921
+ },
2922
+ onBlur() {
2923
+ const element$1 = inputRef.current;
2924
+ if (!element$1 || disabled$1) return;
2925
+ setTouched(true);
2926
+ setFocused(false);
2927
+ if (validationMode === "onBlur") validation.commit(element$1.checked);
2928
+ },
2929
+ onClick(event) {
2930
+ if (readOnly || disabled$1) return;
2931
+ event.preventDefault();
2932
+ const input = inputRef.current;
2933
+ if (!input) return;
2934
+ dispatchClickWithModifiers(input, event);
2755
2935
  }
2756
- element.style.setProperty(property, previousValue, previousPriority);
2757
2936
  };
2758
- }
2759
- /**
2760
- * Temporarily resets inline alignment styles that can distort scroll-based
2761
- * size measurements, then restores them on the next animation frame.
2762
- * @param element - The panel element being measured.
2763
- * @returns A cleanup function that cancels the scheduled restore and reapplies
2764
- * the original inline layout styles immediately.
2765
- */
2766
- function resetLayoutStyles(element) {
2767
- const originalLayoutStyles = {
2768
- "justify-content": element.style.justifyContent,
2769
- "align-items": element.style.alignItems,
2770
- "align-content": element.style.alignContent,
2771
- "justify-items": element.style.justifyItems
2937
+ const inputProps = {
2938
+ ...validation.getValidationProps(disabled$1),
2939
+ checked,
2940
+ disabled: disabled$1,
2941
+ form,
2942
+ id: hiddenInputId,
2943
+ name,
2944
+ required,
2945
+ style: name ? visuallyHiddenInput : visuallyHidden,
2946
+ tabIndex: -1,
2947
+ type: "checkbox",
2948
+ "aria-hidden": true,
2949
+ ref: handleInputRef,
2950
+ onChange(event) {
2951
+ if (event.nativeEvent.defaultPrevented) return;
2952
+ if (readOnly) {
2953
+ event.preventDefault();
2954
+ return;
2955
+ }
2956
+ const nextChecked = event.currentTarget.checked;
2957
+ const eventDetails = createChangeEventDetails(none, event.nativeEvent);
2958
+ onCheckedChange?.(nextChecked, eventDetails);
2959
+ if (eventDetails.isCanceled) return;
2960
+ setCheckedState(nextChecked);
2961
+ },
2962
+ onClick(event) {
2963
+ event.stopPropagation();
2964
+ },
2965
+ onFocus() {
2966
+ switchRef.current?.focus();
2967
+ },
2968
+ ...value !== void 0 ? { value } : EMPTY_OBJECT
2772
2969
  };
2773
- Object.keys(originalLayoutStyles).forEach((key) => {
2774
- element.style.setProperty(key, "initial", "important");
2970
+ const state = react.useMemo(() => ({
2971
+ ...fieldState,
2972
+ checked,
2973
+ disabled: disabled$1,
2974
+ readOnly,
2975
+ required
2976
+ }), [
2977
+ fieldState,
2978
+ checked,
2979
+ disabled$1,
2980
+ readOnly,
2981
+ required
2982
+ ]);
2983
+ const element = useRenderElement("span", componentProps, {
2984
+ state,
2985
+ ref: [
2986
+ forwardedRef,
2987
+ switchRef,
2988
+ buttonRef
2989
+ ],
2990
+ props: [
2991
+ rootProps,
2992
+ elementProps,
2993
+ getButtonProps,
2994
+ (props) => validation.getValidationProps(disabled$1, props)
2995
+ ],
2996
+ stateAttributesMapping: stateAttributesMapping$1
2775
2997
  });
2776
- function restoreLayoutStyles() {
2777
- Object.entries(originalLayoutStyles).forEach(([key, value]) => {
2778
- if (value === "") {
2779
- element.style.removeProperty(key);
2780
- return;
2781
- }
2782
- element.style.setProperty(key, value);
2783
- });
2784
- }
2785
- const frame = AnimationFrame.request(restoreLayoutStyles);
2786
- return () => {
2787
- AnimationFrame.cancel(frame);
2788
- restoreLayoutStyles();
2789
- };
2790
- }
2998
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(SwitchRootContext.Provider, {
2999
+ value: state,
3000
+ children: [
3001
+ element,
3002
+ !checked && name && uncheckedValue !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3003
+ type: "hidden",
3004
+ form,
3005
+ name,
3006
+ value: uncheckedValue,
3007
+ disabled: disabled$1
3008
+ }),
3009
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
3010
+ ...inputProps,
3011
+ suppressHydrationWarning: true
3012
+ })
3013
+ ]
3014
+ });
3015
+ });
2791
3016
 
2792
3017
  //#endregion
2793
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/CollapsiblePanelCssVars.mjs
2794
- let CollapsiblePanelCssVars = /* @__PURE__ */ function(CollapsiblePanelCssVars$1) {
2795
- /**
2796
- * The collapsible panel's height.
2797
- * @type {number}
2798
- */
2799
- CollapsiblePanelCssVars$1["collapsiblePanelHeight"] = "--collapsible-panel-height";
2800
- /**
2801
- * The collapsible panel's width.
2802
- * @type {number}
2803
- */
2804
- CollapsiblePanelCssVars$1["collapsiblePanelWidth"] = "--collapsible-panel-width";
2805
- return CollapsiblePanelCssVars$1;
2806
- }({});
3018
+ //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/switch/thumb/SwitchThumb.mjs
3019
+ /**
3020
+ * The movable part of the switch that indicates whether the switch is on or off.
3021
+ * Renders a `<span>`.
3022
+ *
3023
+ * Documentation: [Base UI Switch](https://base-ui.com/react/components/switch)
3024
+ */
3025
+ const SwitchThumb = /* @__PURE__ */ react.forwardRef(function SwitchThumb$1(componentProps, forwardedRef) {
3026
+ const { render, className, style,...elementProps } = componentProps;
3027
+ return useRenderElement("span", componentProps, {
3028
+ state: useSwitchRootContext(),
3029
+ ref: forwardedRef,
3030
+ stateAttributesMapping: stateAttributesMapping$1,
3031
+ props: elementProps
3032
+ });
3033
+ });
2807
3034
 
2808
3035
  //#endregion
2809
- //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/collapsible/panel/CollapsiblePanel.mjs
3036
+ //#region src/client/switch.ts
2810
3037
  /**
2811
- * A panel with the collapsible contents.
2812
- * Renders a `<div>` element.
3038
+ * The capability switch, in one place for both panels.
2813
3039
  *
2814
- * Documentation: [Base UI Collapsible](https://base-ui.com/react/components/collapsible)
3040
+ * dsh 0.1.7 ships a design-system `Switch` (36×20 capsule, brand-primary on
3041
+ * state, its own disabled dimming and focus ring) — using it keeps the panel's
3042
+ * toggles pixel-identical to every settings page the host ships, which is the
3043
+ * alignment this file exists for. Hosts older than that export fall back to
3044
+ * the local Base UI rendition below, so one build still serves both
3045
+ * generations; the probe runs per call, the same way the icon table resolves.
2815
3046
  */
2816
- const CollapsiblePanel = /* @__PURE__ */ react.forwardRef(function CollapsiblePanel$1(componentProps, forwardedRef) {
2817
- const { className, hiddenUntilFound: hiddenUntilFoundProp, keepMounted: keepMountedProp, render, id: idProp, style,...elementProps } = componentProps;
2818
- const { defaultPanelId, mounted, onOpenChange, open, setMounted, setPanelIdState, setOpen, state, transitionStatus } = useCollapsibleRootContext();
2819
- const hiddenUntilFound = hiddenUntilFoundProp ?? false;
2820
- const keepMounted = keepMountedProp ?? false;
2821
- const registeredId = idProp || void 0;
2822
- const id = registeredId ?? defaultPanelId;
2823
- useIsoLayoutEffect(() => {
2824
- setPanelIdState((currentId) => registeredId ?? (currentId === null ? void 0 : currentId));
2825
- return () => {
2826
- setPanelIdState((currentId) => currentId === registeredId ? null : currentId);
2827
- };
2828
- }, [registeredId, setPanelIdState]);
2829
- const { height, props, ref, shouldPreventOpenAnimation, shouldRender, transitionStatus: panelTransitionStatus, width } = useCollapsiblePanel({
2830
- externalRef: forwardedRef,
2831
- hiddenUntilFound,
2832
- id,
2833
- keepMounted,
2834
- mounted,
2835
- onOpenChange,
2836
- open,
2837
- setMounted,
2838
- setOpen,
2839
- transitionStatus
2840
- });
2841
- const panelState = {
2842
- ...state,
2843
- transitionStatus: panelTransitionStatus
2844
- };
2845
- const resolvedStyle = resolveStyle(style, panelState);
2846
- const element = useRenderElement("div", {
2847
- ...componentProps,
2848
- style: void 0
2849
- }, {
2850
- state: panelState,
2851
- ref,
2852
- props: [
2853
- props,
2854
- { style: {
2855
- [CollapsiblePanelCssVars.collapsiblePanelHeight]: height === void 0 ? "auto" : `${height}px`,
2856
- [CollapsiblePanelCssVars.collapsiblePanelWidth]: width === void 0 ? "auto" : `${width}px`
2857
- } },
2858
- elementProps,
2859
- resolvedStyle ? { style: resolvedStyle } : void 0,
2860
- shouldPreventOpenAnimation ? { style: { animationName: "none" } } : void 0
2861
- ],
2862
- stateAttributesMapping: collapsibleStateAttributesMapping
3047
+ function capabilitySwitch(options) {
3048
+ const inert = options.disabled || options.busy;
3049
+ const HostSwitch = __deepseek_ai_dsh_client_ui_primitives.Switch;
3050
+ if (HostSwitch !== void 0) return react.createElement(HostSwitch, {
3051
+ checked: options.checked,
3052
+ onChange: options.onCheckedChange,
3053
+ label: options.label,
3054
+ disabled: inert
2863
3055
  });
2864
- if (!shouldRender) return null;
2865
- return element;
2866
- });
3056
+ return react.createElement(SwitchRoot, {
3057
+ className: "ci-switch",
3058
+ checked: options.checked,
3059
+ disabled: inert,
3060
+ "aria-label": options.label,
3061
+ onCheckedChange: options.onCheckedChange,
3062
+ style: {
3063
+ position: "relative",
3064
+ width: "32px",
3065
+ height: "18px",
3066
+ padding: 0,
3067
+ border: "none",
3068
+ borderRadius: "999px",
3069
+ background: options.checked ? TOK.switchOn : TOK.switchOff,
3070
+ cursor: inert ? "not-allowed" : "pointer",
3071
+ opacity: options.busy ? .65 : 1,
3072
+ flex: "0 0 auto"
3073
+ }
3074
+ }, react.createElement(SwitchThumb, {
3075
+ className: "ci-thumb",
3076
+ style: {
3077
+ display: "block",
3078
+ width: "14px",
3079
+ height: "14px",
3080
+ margin: "2px",
3081
+ borderRadius: "999px",
3082
+ background: TOK.switchThumb,
3083
+ boxShadow: "0 1px 2px rgba(0,0,0,.22)",
3084
+ transform: options.checked ? "translateX(14px)" : "translateX(0)",
3085
+ transition: `transform .12s ${TOK.switchEase}`
3086
+ }
3087
+ }));
3088
+ }
2867
3089
 
2868
3090
  //#endregion
2869
3091
  //#region node_modules/.pnpm/@base-ui+utils@0.3.2_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/utils/platform/shared.mjs
@@ -4577,97 +4799,18 @@ const TabsList = /* @__PURE__ */ react.forwardRef(function TabsList$1(componentP
4577
4799
  });
4578
4800
 
4579
4801
  //#endregion
4580
- //#region src/client/icons.ts
4581
- /** Rendered when a host generation has neither name: the panel stays usable. */
4582
- const MissingIcon = () => null;
4583
- /**
4584
- * Pick the first export name the host's primitives package actually provides.
4585
- * Exported separately from the module-level constants so tests can drive every
4586
- * branch with a fake table.
4587
- */
4588
- function pickIcon(table$1, modern, legacy) {
4589
- const found = table$1[modern] ?? table$1[legacy];
4590
- return typeof found === "function" ? found : MissingIcon;
4802
+ //#region src/client/row-icon.ts
4803
+ /** A skill row leads with the host's own skill glyph. */
4804
+ function skillRowIcon() {
4805
+ return react.createElement(IconSkill, { size: 14 });
4591
4806
  }
4592
- const table = __deepseek_ai_dsh_client_ui_primitives;
4593
- const IconChevronRight = pickIcon(table, "IconChevronRightOutlineRegular", "IconChevronRightOutline14");
4594
- const IconContextInjection = pickIcon(table, "IconContextInjectionOutlineRegular", "IconContextInjectionOutline16");
4595
- const IconFolderClose = pickIcon(table, "IconFolderCloseRegular", "IconFolderClose16");
4596
- const IconSend = pickIcon(table, "IconSendOutlineRegular", "IconSendOutline14");
4597
- const IconSearch = pickIcon(table, "IconSearchOutlineRegular", "IconSearchOutline16");
4598
- const IconRefresh = pickIcon(table, "IconRefreshOutlineRegular", "IconRefreshOutline14");
4599
- const IconChevronDown = pickIcon(table, "IconChevronDownOutlineRegular", "IconChevronDownOutline14");
4600
- const IconSettings = pickIcon(table, "IconSettingsOutlineRegular", "IconSettingsOutline16");
4601
- /**
4602
- * Whether the host ships the 0.1.7 stroke-weight icon set. Exported as a
4603
- * function so tests can drive both branches; the module constant resolves it
4604
- * against the real package.
4605
- *
4606
- * One consumer: the footer settings entry. The `settings.open` keybinding that
4607
- * entry drives shipped in the SAME host generation as the renamed icon set
4608
- * (verified: 0.1.6's settings bundle has no such binding), so this is the
4609
- * closest client-visible signal that the shortcut exists. If a future host
4610
- * renames icons again this reads false and the entry hides — the safe
4611
- * direction.
4612
- */
4613
- function hasModernShell(table$1) {
4614
- return typeof table$1["IconSettingsOutlineRegular"] === "function";
4807
+ /** An MCP server row leads with the host's own extension glyph. */
4808
+ function serverRowIcon() {
4809
+ return react.createElement(IconCordisPlugin, { size: 14 });
4615
4810
  }
4616
- const HOST_HAS_MODERN_SHELL = hasModernShell(table);
4617
-
4618
- //#endregion
4619
- //#region src/client/disclosure-row.ts
4620
- /**
4621
- * The chevron both panels use. Kept here rather than copied into each panel:
4622
- * the two had already drifted apart in geometry once, which is exactly the
4623
- * failure a shared control prevents.
4624
- */
4625
- const chevronIcon = react.createElement("svg", {
4626
- width: 12,
4627
- height: 12,
4628
- viewBox: "0 0 16 16",
4629
- fill: "none",
4630
- "aria-hidden": true
4631
- }, react.createElement("path", {
4632
- d: "M6 3.5 10.5 8 6 12.5",
4633
- stroke: "currentColor",
4634
- strokeWidth: 1.4,
4635
- strokeLinecap: "round",
4636
- strokeLinejoin: "round"
4637
- }));
4638
- /**
4639
- * One capability row that may reveal detail.
4640
- *
4641
- * Both panels show the same kind of thing — a name, a switch, and detail worth
4642
- * hiding until asked for — so both get the same affordance from one place. A
4643
- * row with no detail renders no trigger at all rather than an empty one, and
4644
- * takes a spacer so its name still lines up with the rows that do.
4645
- */
4646
- function disclosureRow(options) {
4647
- if (!(options.detail !== void 0 && options.detail !== null && options.detail !== "")) return react.createElement("div", {
4648
- className: options.className,
4649
- ...options.style === void 0 ? {} : { style: options.style }
4650
- }, react.createElement("div", { className: options.headerClassName }, react.createElement("span", {
4651
- "aria-hidden": true,
4652
- ...options.spacerClassName === void 0 ? { style: {
4653
- width: "18px",
4654
- flex: "none"
4655
- } } : { className: options.spacerClassName }
4656
- }), options.heading, ...options.actions));
4657
- const disclosure = resolveDisclosure(options.expanded, options.filtering);
4658
- return react.createElement(CollapsibleRoot, {
4659
- open: disclosure.open,
4660
- onOpenChange: options.onOpenChange,
4661
- className: options.className,
4662
- ...options.style === void 0 ? {} : { style: options.style }
4663
- }, react.createElement("div", { className: options.headerClassName }, react.createElement(CollapsibleTrigger, {
4664
- className: "ci-disclosure-trigger",
4665
- disabled: disclosure.disabled,
4666
- "aria-label": options.triggerLabel
4667
- }, react.createElement("span", {
4668
- className: "ci-chevron",
4669
- "aria-hidden": true
4670
- }, chevronIcon), options.heading), ...options.actions), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, options.detail));
4811
+ /** Every tool row leads with the host's unclassified-tool glyph. */
4812
+ function toolRowIcon() {
4813
+ return react.createElement(IconSparkle, { size: 14 });
4671
4814
  }
4672
4815
 
4673
4816
  //#endregion
@@ -5078,7 +5221,7 @@ function PresetToolSection(props) {
5078
5221
  opacity: 0,
5079
5222
  transition: "opacity 0.15s"
5080
5223
  }
5081
- }, react.createElement(IconFolderClose, { size: 12 })) : null, `${label} (${items.length})`), rule(true)));
5224
+ }, react.createElement(IconFolderClose, { size: 14 })) : null, `${label} (${items.length})`), rule(true)));
5082
5225
  };
5083
5226
  const toggle$1 = (tool, presetId) => switchFor(tool.enabled, tool.reserved === true, tool.reserved === true ? t("preset.reserved", { name: tool.label }) : t(tool.enabled ? "action.disable" : "action.enable", { name: tool.label }), (checked) => {
5084
5227
  setPresetTool(presetId, tool.name, checked);
@@ -5115,6 +5258,7 @@ function PresetToolSection(props) {
5115
5258
  className: "ci-preset-disclosure",
5116
5259
  headerClassName: "ci-row-head ci-preset-tool-row",
5117
5260
  spacerClassName: "ci-preset-spacer",
5261
+ icon: skillRowIcon(),
5118
5262
  heading: react.createElement("span", { className: "ci-preset-tool-name" }, skill.name, skill.project === true ? react.createElement("span", { className: "ci-preset-badge" }, t("preset.projectSkill")) : null),
5119
5263
  actions: [switchFor(skill.enabled, false, t(skill.enabled ? "action.disable" : "action.enable", { name: skill.name }), (checked) => {
5120
5264
  setPresetSkill(presetId, skill.name, checked);
@@ -5141,6 +5285,7 @@ function PresetToolSection(props) {
5141
5285
  className: "ci-preset-disclosure",
5142
5286
  headerClassName: "ci-row-head ci-preset-tool-row",
5143
5287
  spacerClassName: "ci-preset-spacer",
5288
+ icon: toolRowIcon(),
5144
5289
  heading: react.createElement("span", { className: "ci-preset-tool-name" }, tool.label),
5145
5290
  actions: [toggle$1(tool, presetId)],
5146
5291
  ...tool.description === void 0 ? {} : { detail: react.createElement("div", { className: "ci-preset-detail" }, tool.description) }
@@ -5174,10 +5319,7 @@ function PresetToolSection(props) {
5174
5319
  [key]: next
5175
5320
  }));
5176
5321
  }
5177
- }, react.createElement(CollapsibleTrigger, { className: "ci-preset-part-trigger" }, react.createElement("span", {
5178
- className: "ci-chevron",
5179
- "aria-hidden": true
5180
- }, chevronIcon), react.createElement("h3", { className: "ci-preset-part-title" }, title)), react.createElement("p", { className: "ci-preset-part-sub" }, t("group.count", {
5322
+ }, react.createElement(CollapsibleTrigger, { className: "ci-preset-part-trigger" }, react.createElement(IconTriangleRight, { size: 14 }), react.createElement("h3", { className: "ci-preset-part-title" }, title)), react.createElement("p", { className: "ci-preset-part-sub" }, t("group.count", {
5181
5323
  shown,
5182
5324
  total
5183
5325
  })), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, react.createElement("ul", { className: "ci-preset-tool-list" }, ...rows))));
@@ -5200,10 +5342,7 @@ function PresetToolSection(props) {
5200
5342
  }, react.createElement("div", { className: "ci-row-head ci-preset-tool-row" }, react.createElement(CollapsibleTrigger, {
5201
5343
  className: "ci-disclosure-trigger ci-preset-server-trigger",
5202
5344
  disabled: disclosure.disabled
5203
- }, react.createElement("span", {
5204
- className: "ci-chevron",
5205
- "aria-hidden": true
5206
- }, chevronIcon), react.createElement("span", { className: "ci-preset-tool-copy" }, react.createElement("span", { className: "ci-preset-tool-name" }, server.server), server.unavailable === true ? null : react.createElement("span", { className: "ci-preset-tool-description" }, server.tools.length === 1 ? t("server.tool.one") : t("server.tools", { count: server.tools.length })))), server.unavailable === true ? react.createElement("span", {
5345
+ }, leadingFor(serverRowIcon(), disclosure.open), react.createElement("span", { className: "ci-preset-tool-copy" }, react.createElement("span", { className: "ci-preset-tool-name" }, server.server), server.unavailable === true ? null : react.createElement("span", { className: "ci-preset-tool-description" }, server.tools.length === 1 ? t("server.tool.one") : t("server.tools", { count: server.tools.length })))), server.unavailable === true ? react.createElement("span", {
5207
5346
  className: "ci-preset-badge",
5208
5347
  title: t("server.unavailableHint")
5209
5348
  }, t("server.unavailable")) : switchFor(server.enabled, false, t(server.enabled ? "action.disable" : "action.enable", { name: server.server }), (checked) => {
@@ -5226,7 +5365,7 @@ function PresetToolSection(props) {
5226
5365
  }, react.createElement("span", {
5227
5366
  className: "ci-reconnect-glyph",
5228
5367
  "aria-hidden": true
5229
- }, react.createElement(IconRefresh, { size: 12 })), t("action.reload.label")) : null), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, react.createElement("ul", { className: "ci-preset-tool-list" }, ...server.tools.map((tool) => toolRow(tool, selected.id, true))))));
5368
+ }, react.createElement(IconRefresh, { size: 14 })), t("action.reload.label")) : null), react.createElement(CollapsiblePanel, { className: "ci-collapse" }, react.createElement("ul", { className: "ci-preset-tool-list" }, ...server.tools.map((tool) => toolRow(tool, selected.id, true))))));
5230
5369
  };
5231
5370
  group("mcp", t("tab.mcp"), groupBy(view.mcp, (server) => server.source === void 0 || server.source === "host" ? "host" : `preset:${server.source}`).flatMap(([groupKey, items], i) => [sourceDivider(groupKey, items, i === 0), ...items.map((server) => serverRow(server))]), totals.mcp, view.mcp.length);
5232
5371
  group("system", t("group.systemTools"), view.systemTools.map((tool) => toolRow(tool, selected.id, false)), totals.systemTools, view.systemTools.length);
@@ -5242,7 +5381,7 @@ function PresetToolSection(props) {
5242
5381
  }, t("status.loading")) : null, state.payload === null ? null : react.createElement(react.Fragment, null, writable ? null : react.createElement("p", {
5243
5382
  role: "note",
5244
5383
  className: "ci-settings-note"
5245
- }, t("preset.readonly")), react.createElement("div", { className: "ci-preset-toolbar" }, react.createElement("div", { className: "ci-search" }, react.createElement(IconSearch, { size: 16 }), react.createElement(Input, {
5384
+ }, t("preset.readonly")), react.createElement("div", { className: "ci-preset-toolbar" }, react.createElement("div", { className: "ci-search" }, react.createElement(IconSearch, { size: 14 }), react.createElement(Input, {
5246
5385
  className: "ci-filter ci-preset-filter",
5247
5386
  value: query,
5248
5387
  placeholder: t("filter.placeholder"),
@@ -5343,6 +5482,41 @@ function PresetToolSection(props) {
5343
5482
  })), body()));
5344
5483
  }
5345
5484
 
5485
+ //#endregion
5486
+ //#region src/client/preview.ts
5487
+ /**
5488
+ * Read the Host's sidebar navigation, or `undefined` when this deployment has
5489
+ * none. The returned closure keeps the service as its receiver: it is a live
5490
+ * object whose methods arrive through a guarding proxy, so detaching one and
5491
+ * calling it bare would drop `this`.
5492
+ * @param ctx - the plugin context; only its optional-lookup channel is used.
5493
+ * @returns an opener for a `dsh-resource://file/…` address, or `undefined`.
5494
+ */
5495
+ function resolvePreviewOpener(ctx) {
5496
+ const service = ctx.get("sidebarRight");
5497
+ if (service === null || typeof service !== "object" && typeof service !== "function") return void 0;
5498
+ const open = service.openResource;
5499
+ if (typeof open !== "function") return void 0;
5500
+ return (address) => {
5501
+ open.call(service, address);
5502
+ };
5503
+ }
5504
+ /**
5505
+ * Open a resource address in the Host's right sidebar, looking the service up
5506
+ * at the moment of the click rather than once when the panel activates.
5507
+ *
5508
+ * Cordis starts the sidebar's own fiber when IT is ready, which is not
5509
+ * necessarily before this panel's: resolving once at activation would read
5510
+ * `undefined` whenever the panel won that race and then never retry, silently
5511
+ * removing an action the row should have had — a failure with no error to see.
5512
+ * The Host's own skill package avoids the race by declaring `sidebarRight` as a
5513
+ * required inject, which cordis holds the fiber for; this panel cannot afford
5514
+ * that, since an absent sidebar would take the skills/MCP/tools panel with it.
5515
+ */
5516
+ function openPreviewResource(ctx, address) {
5517
+ resolvePreviewOpener(ctx)?.(address);
5518
+ }
5519
+
5346
5520
  //#endregion
5347
5521
  //#region node_modules/.pnpm/@base-ui+react@1.7.0_@types+react@18.3.31_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@base-ui/react/floating-ui-react/hooks/useHoverShared.mjs
5348
5522
  function resolveValue(value, pointerType) {
@@ -11112,15 +11286,24 @@ function apply(ctx) {
11112
11286
  style.remove();
11113
11287
  };
11114
11288
  }, "capability-panel: stylesheet");
11115
- /** Host iconography: the panel inspects what lands in the session's context. */
11116
- const layersIcon = (size$3) => h(IconContextInjection, { size: size$3 });
11289
+ /** The trigger's mark: the host's sliders artwork, the same family its own
11290
+ * option popovers wear (ui-workspace draws the two-row sibling). The panel
11291
+ * is a set of per-session switches, and the glyph it replaced — the host's
11292
+ * context-injection box — read as one more box-with-an-arrow. */
11293
+ const slidersIcon = (size$3) => h(IconSliders, { size: size$3 });
11117
11294
  /** Magnifier sitting inside the filter input. */
11118
11295
  const searchIcon = (size$3) => h(IconSearch, { size: size$3 });
11119
- /** Paper plane: the row action lands the command in the composer,
11120
- * ready for the user's own Enter. */
11121
- const insertIcon = (size$3) => h(IconSend, { size: size$3 });
11296
+ /** Plus: the row action adds the skill's slash command to the composer draft.
11297
+ * The host uses this glyph for "add" everywhere (model, workspace, task), and
11298
+ * unlike the send arrow it makes no promise that anything is submitted. */
11299
+ const insertIcon = (size$3) => h(IconPlus, { size: size$3 });
11122
11300
  /** Circular arrows: pull a declared-but-offline server's connection up now. */
11123
11301
  const reconnectIcon = (size$3) => h(IconRefresh, { size: size$3 });
11302
+ /** Panel mark: the destination of the row action, so it wears the glyph both
11303
+ * host sidebars draw for the side panel (ui-sidebar-right's expand/collapse).
11304
+ * The arrow it replaced (↗) meant "open elsewhere" and sat beside a second
11305
+ * arrow. */
11306
+ const previewIcon = (size$3) => h(IconPanelLeft, { size: size$3 });
11124
11307
  /** The GitHub mark. Not in the host icon set (brand logos are not shipped
11125
11308
  * there), so this one path is inlined for the feedback link's recognizability. */
11126
11309
  const githubIcon = (size$3) => h("svg", {
@@ -11286,7 +11469,7 @@ function apply(ctx) {
11286
11469
  opacity: 0,
11287
11470
  transition: "opacity 0.15s"
11288
11471
  }
11289
- }, h(IconFolderClose, { size: 12 })) : null, `${label} (${count})`), rule(true));
11472
+ }, h(IconFolderClose, { size: 14 })) : null, `${label} (${count})`), rule(true));
11290
11473
  };
11291
11474
  /** Group items by source, preserving order within each group. */
11292
11475
  const groupBySource = (items, getSource) => {
@@ -11357,8 +11540,6 @@ function apply(ctx) {
11357
11540
  if (sessionId !== null) setCapability(sessionId, kind, name, checked);
11358
11541
  }
11359
11542
  });
11360
- /** Right chevron the disclosure CSS rotates 90° when expanded. */
11361
- const chevronIcon$1 = h(IconChevronRight, { size: 12 });
11362
11543
  const groupLabel = (text, first) => h("div", {
11363
11544
  key: `group:${text}`,
11364
11545
  style: {
@@ -11402,7 +11583,7 @@ function apply(ctx) {
11402
11583
  * trigger owns only chevron + label; trailing actions remain independent
11403
11584
  * buttons and never toggle the description.
11404
11585
  */
11405
- const disclosureRow$1 = (key, enabled, label, description, actions, className = ROW_ROOT_CLASS, sourceLabel) => {
11586
+ const disclosureRow$1 = (key, enabled, label, description, actions, className = ROW_ROOT_CLASS, sourceLabel, rowIcon) => {
11406
11587
  const hasDescription = description !== void 0 && description !== "";
11407
11588
  const disclosure = resolveDisclosure(expanded[key] === true, filtering);
11408
11589
  const ariaLabel = disclosureAria(label, "detail.description", disclosure);
@@ -11410,10 +11591,10 @@ function apply(ctx) {
11410
11591
  key,
11411
11592
  className,
11412
11593
  style: { opacity: enabled ? 1 : .55 }
11413
- }, h("div", { className: ROW_HEADER_CLASS }, h("span", { style: {
11594
+ }, h("div", { className: ROW_HEADER_CLASS }, rowIcon === void 0 ? h("span", { style: {
11414
11595
  width: "18px",
11415
11596
  flex: "none"
11416
- } }), nameText(label, sourceLabel), ...actions));
11597
+ } }) : leadingStatic(rowIcon), nameText(label, sourceLabel), ...actions));
11417
11598
  return h(CollapsibleRoot, {
11418
11599
  key,
11419
11600
  open: disclosure.open,
@@ -11426,10 +11607,7 @@ function apply(ctx) {
11426
11607
  className: "ci-disclosure-trigger",
11427
11608
  disabled: disclosure.disabled,
11428
11609
  "aria-label": ariaLabel
11429
- }, h("span", {
11430
- className: "ci-chevron",
11431
- "aria-hidden": true
11432
- }, chevronIcon$1), nameText(label, sourceLabel)), ...actions), h(CollapsiblePanel, { className: "ci-collapse" }, h("div", { className: "ci-description" }, description)));
11610
+ }, leadingFor(rowIcon, disclosure.open), nameText(label, sourceLabel)), ...actions), h(CollapsiblePanel, { className: "ci-collapse" }, h("div", { className: "ci-description" }, description)));
11433
11611
  };
11434
11612
  /**
11435
11613
  * Put a skill's slash command into the composer — never auto-submit:
@@ -11449,14 +11627,22 @@ function apply(ctx) {
11449
11627
  actions.setDraft(draft.trim() === "" ? `/${name} ` : `${draft} /${name} `);
11450
11628
  close();
11451
11629
  };
11452
- const insertButton = (name) => h("button", {
11630
+ /**
11631
+ * The row's hover-revealed action slot. `.ci-row-head .ci-send` keeps it
11632
+ * invisible until the row is hovered or focused, so a row of controls stays
11633
+ * quiet until the pointer is on it; both row actions share that slot and
11634
+ * its 20×20 ghost chrome.
11635
+ *
11636
+ * The button carries `aria-label` only, no `title`: the host's own controls
11637
+ * show a delayed `Tooltip` rather than the browser's instant native one,
11638
+ * and the sibling action in this same slot has never had a title.
11639
+ */
11640
+ const iconAction = (label, icon, onClick, disabled$1 = false) => h("button", {
11453
11641
  type: "button",
11454
11642
  className: "ci-iconbtn ci-send",
11455
- "aria-label": t("action.insert", { name }),
11456
- disabled: props.inputActions === void 0,
11457
- onClick: () => {
11458
- insertCommand(name);
11459
- },
11643
+ "aria-label": label,
11644
+ disabled: disabled$1,
11645
+ onClick,
11460
11646
  style: {
11461
11647
  display: "grid",
11462
11648
  placeItems: "center",
@@ -11467,18 +11653,38 @@ function apply(ctx) {
11467
11653
  borderRadius: "999px",
11468
11654
  background: "transparent",
11469
11655
  color: TOK.textTertiary,
11470
- cursor: props.inputActions === void 0 ? "not-allowed" : "pointer",
11656
+ cursor: disabled$1 ? "not-allowed" : "pointer",
11471
11657
  flex: "none",
11472
11658
  font: "inherit"
11473
11659
  }
11474
- }, insertIcon(12));
11660
+ }, icon);
11661
+ const insertButton = (name) => iconAction(t("action.insert", { name }), insertIcon(12), () => {
11662
+ insertCommand(name);
11663
+ }, props.inputActions === void 0);
11664
+ /**
11665
+ * Show this skill's instruction file where the Host's own skill references
11666
+ * show it: the right-sidebar preview, which renders its Markdown. The
11667
+ * panel offers this whenever the row carries an address, which the Host
11668
+ * computes from the skill's instruction file — a skill the runtime
11669
+ * registered in memory has no file, and a Host predating the addressing
11670
+ * grammar cannot name one, and both ship no address at all. The sidebar
11671
+ * service itself is looked up on click, not here: see `preview.ts`.
11672
+ */
11673
+ const previewButton = (skill) => {
11674
+ const address = skill.fileAddress;
11675
+ if (address === void 0) return null;
11676
+ return iconAction(t("action.preview", { name: skill.name }), previewIcon(12), () => {
11677
+ openPreviewResource(ctx, address);
11678
+ });
11679
+ };
11475
11680
  const skillRow = (skill) => disclosureRow$1(`skill:${skill.name}`, skill.enabled, skill.name, skill.description, [
11476
11681
  stateMeta(skill),
11682
+ previewButton(skill),
11477
11683
  insertButton(skill.name),
11478
11684
  blockedChip(blocked[skill.name] ?? 0),
11479
11685
  switchControl("skill", skill.name, skill.enabled)
11480
- ], ROW_ROOT_CLASS);
11481
- const mcpToolRow = (tool, serverEnabled) => disclosureRow$1(`mcp-tool:${tool.name}`, tool.enabled, tool.label, tool.description, [blockedChip(blocked[tool.name] ?? 0), serverEnabled ? switchControl("mcp-tool", tool.name, tool.enabled) : null], MCP_TOOL_ROOT_CLASS);
11686
+ ], ROW_ROOT_CLASS, void 0, skillRowIcon());
11687
+ const mcpToolRow = (tool, serverEnabled) => disclosureRow$1(`mcp-tool:${tool.name}`, tool.enabled, tool.label, tool.description, [blockedChip(blocked[tool.name] ?? 0), serverEnabled ? switchControl("mcp-tool", tool.name, tool.enabled) : null], MCP_TOOL_ROOT_CLASS, void 0, toolRowIcon());
11482
11688
  const serverRow = (server) => {
11483
11689
  const serverBlocked = server.tools.reduce((sum, tool) => sum + (blocked[tool.name] ?? 0), 0);
11484
11690
  const key = `mcp:${server.server}`;
@@ -11509,10 +11715,7 @@ function apply(ctx) {
11509
11715
  flex: "none",
11510
11716
  font: "inherit"
11511
11717
  }
11512
- }, h("span", {
11513
- className: "ci-chevron",
11514
- "aria-hidden": true
11515
- }, chevronIcon$1)), nameText(server.server), server.unavailable === true ? h("span", {
11718
+ }, leadingFor(serverRowIcon(), disclosure.open)), nameText(server.server), server.unavailable === true ? h("span", {
11516
11719
  className: "ci-preset-badge",
11517
11720
  title: t("server.unavailableHint"),
11518
11721
  style: { flex: "none" }
@@ -11528,14 +11731,14 @@ function apply(ctx) {
11528
11731
  }, h("span", {
11529
11732
  className: "ci-reconnect-glyph",
11530
11733
  "aria-hidden": true
11531
- }, reconnectIcon(12)), t("action.reload.label")) : null, server.unavailable === true ? null : switchControl("mcp-server", server.server, server.enabled)), h(CollapsiblePanel, { className: "ci-collapse" }, h("div", { style: {
11734
+ }, reconnectIcon(14)), t("action.reload.label")) : null, server.unavailable === true ? null : switchControl("mcp-server", server.server, server.enabled)), h(CollapsiblePanel, { className: "ci-collapse" }, h("div", { style: {
11532
11735
  marginTop: "2px",
11533
11736
  marginLeft: "4px",
11534
11737
  paddingLeft: "8px",
11535
11738
  borderLeft: `2px solid ${TOK.border}`
11536
11739
  } }, ...server.tools.map((tool) => mcpToolRow(tool, server.enabled)))));
11537
11740
  };
11538
- const systemRow = (tool) => disclosureRow$1(`sys:${tool.name}`, tool.enabled, tool.label, tool.description, [blockedChip(blocked[tool.name] ?? 0), tool.reserved === true ? null : switchControl("system-tool", tool.name, tool.enabled)]);
11741
+ const systemRow = (tool) => disclosureRow$1(`sys:${tool.name}`, tool.enabled, tool.label, tool.description, [blockedChip(blocked[tool.name] ?? 0), tool.reserved === true ? null : switchControl("system-tool", tool.name, tool.enabled)], ROW_ROOT_CLASS, void 0, toolRowIcon());
11539
11742
  const emptyNote = (text) => h("div", {
11540
11743
  key: `empty:${text}`,
11541
11744
  style: {
@@ -11632,7 +11835,7 @@ function apply(ctx) {
11632
11835
  flex: "none",
11633
11836
  font: "inherit"
11634
11837
  }
11635
- }, layersIcon(14))), h(PopoverPortal, {}, h(PopoverPositioner, {
11838
+ }, slidersIcon(14))), h(PopoverPortal, {}, h(PopoverPositioner, {
11636
11839
  side: "top",
11637
11840
  align: "end",
11638
11841
  sideOffset: 8,
@@ -11682,7 +11885,7 @@ function apply(ctx) {
11682
11885
  color: TOK.textTertiary,
11683
11886
  display: "grid",
11684
11887
  pointerEvents: "none"
11685
- } }, searchIcon(12)), h(Input, {
11888
+ } }, searchIcon(14)), h(Input, {
11686
11889
  className: "ci-filter",
11687
11890
  value: query,
11688
11891
  placeholder: t("filter.placeholder"),
@@ -11763,7 +11966,7 @@ function apply(ctx) {
11763
11966
  }, h("span", {
11764
11967
  className: "ci-feedback-icon",
11765
11968
  "aria-hidden": true
11766
- }, h(IconSettings, { size: 12 })), t("footer.openSettings")) : h("span");
11969
+ }, h(IconSettings, { size: 16 })), t("footer.openSettings")) : h("span");
11767
11970
  })(), h("a", {
11768
11971
  href: FEEDBACK_URL,
11769
11972
  target: "_blank",