@xenosystem/blocks 0.11.0 → 0.11.2

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.
@@ -3356,6 +3356,20 @@ function XIcon({ size = 10 }) {
3356
3356
 
3357
3357
  // src/edit/inspector/react/widgets.tsx
3358
3358
  import { useCallback as useCallback2, useRef as useRef3 } from "react";
3359
+ import {
3360
+ AxisLabel,
3361
+ IconButton,
3362
+ Input,
3363
+ ProportionBar,
3364
+ SegmentedControl,
3365
+ Select,
3366
+ Stack,
3367
+ Swatch,
3368
+ Text,
3369
+ TextArea,
3370
+ TextButton,
3371
+ Toggle
3372
+ } from "@xenosystem/components/chrome";
3359
3373
  import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
3360
3374
  function displayText(field, controller) {
3361
3375
  const draft = controller.getDraft(field.id);
@@ -3381,10 +3395,7 @@ function useEditingHandlers(field, controller) {
3381
3395
  },
3382
3396
  [controller, field.id]
3383
3397
  );
3384
- const onChange = useCallback2(
3385
- (e) => controller.setDraft(field.id, e.target.value),
3386
- [controller, field.id]
3387
- );
3398
+ const onChange = useCallback2((value) => controller.setDraft(field.id, value), [controller, field.id]);
3388
3399
  const onBlur = useCallback2(() => controller.commitDraft(field.id), [controller, field.id]);
3389
3400
  const onKeyDown = useCallback2(
3390
3401
  (e) => {
@@ -3467,76 +3478,44 @@ function NumberWidget({ field, controller, component }) {
3467
3478
  const v = Array.isArray(raw) ? raw[component] : void 0;
3468
3479
  return typeof v === "number" ? formatNumeric(v, field) : "";
3469
3480
  })() : displayText(field, controller);
3470
- return /* @__PURE__ */ jsxs4("span", { style: S2.numberCell, children: [
3471
- component !== void 0 && field.components?.[component] && /* @__PURE__ */ jsx5(
3472
- "span",
3473
- {
3474
- style: { ...S2.axisLabel, cursor: editable ? "ew-resize" : "default" },
3475
- onPointerDown,
3476
- onPointerMove,
3477
- onPointerUp,
3478
- children: field.components[component]
3479
- }
3480
- ),
3481
+ const position = numericValue === null ? null : valueToPosition(numericValue, field);
3482
+ return /* @__PURE__ */ jsxs4(Stack, { direction: "row", gap: 2, pad: "none", children: [
3483
+ component !== void 0 && field.components?.[component] ? /* @__PURE__ */ jsx5(AxisLabel, { scrubbable: editable, onPointerDown, onPointerMove, onPointerUp, children: field.components[component] }) : null,
3481
3484
  /* @__PURE__ */ jsx5(
3482
- "input",
3485
+ Input,
3483
3486
  {
3484
- type: "text",
3485
3487
  inputMode: "decimal",
3486
3488
  value: text,
3487
3489
  placeholder: mixed ? controller.getMixedPlaceholder() : field.placeholder,
3490
+ mixed,
3488
3491
  readOnly: !editable,
3489
3492
  disabled: field.disabled,
3493
+ label: field.components?.[component ?? -1] ? `${field.label} ${field.components[component]}` : field.label,
3490
3494
  onFocus: handlers.onFocus,
3491
3495
  onChange: handlers.onChange,
3492
3496
  onBlur: handlers.onBlur,
3493
3497
  onKeyDown: handlers.onKeyDown,
3494
3498
  onWheel,
3495
- spellCheck: false,
3496
- style: {
3497
- ...S2.input,
3498
- ...mixed ? S2.mixedInput : null,
3499
- ...editable ? null : S2.readOnlyInput
3500
- },
3501
3499
  ...ariaSliderProps(field, numericValue)
3502
3500
  }
3503
3501
  ),
3504
- controller.getNumericMode() === "slider" && numericValue !== null && /* @__PURE__ */ jsx5("span", { style: S2.sliderTrack, "aria-hidden": true, children: /* @__PURE__ */ jsx5("span", { style: { ...S2.sliderFill, width: `${valueToPosition(numericValue, field).toFixed(4) === "NaN" ? 0 : valueToPosition(numericValue, field) * 100}%` } }) })
3502
+ controller.getNumericMode() === "slider" && position !== null && Number.isFinite(position) ? /* @__PURE__ */ jsx5(ProportionBar, { segments: [{ value: position, opacity: 0.9 }, { value: 1 - position, opacity: 0.08 }] }) : null
3505
3503
  ] });
3506
3504
  }
3507
3505
  function VectorWidget({ field, controller }) {
3508
3506
  const expanded = controller.isExpanded(field.id) || !controller.isUniformVector(field.id);
3509
3507
  const value = controller.getFieldValue(field.id);
3510
3508
  const count = Array.isArray(value) ? value.length : field.components?.length ?? 0;
3509
+ const toggle = (label, title) => /* @__PURE__ */ jsx5(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\u22EF" }), label, onClick: () => controller.toggleExpanded(field.id) });
3511
3510
  if (!expanded && field.expandable) {
3512
- return /* @__PURE__ */ jsxs4("span", { style: S2.vectorRow, children: [
3511
+ return /* @__PURE__ */ jsxs4(Stack, { direction: "row", gap: 3, pad: "none", children: [
3513
3512
  /* @__PURE__ */ jsx5(NumberWidget, { field, controller, component: 0 }),
3514
- /* @__PURE__ */ jsx5(
3515
- "button",
3516
- {
3517
- type: "button",
3518
- style: S2.miniBtn,
3519
- onClick: () => controller.toggleExpanded(field.id),
3520
- title: "Edit each axis separately",
3521
- "aria-label": "Expand",
3522
- children: "\u22EF"
3523
- }
3524
- )
3513
+ toggle("Expand", "Edit each axis separately")
3525
3514
  ] });
3526
3515
  }
3527
- return /* @__PURE__ */ jsxs4("span", { style: S2.vectorRow, children: [
3516
+ return /* @__PURE__ */ jsxs4(Stack, { direction: "row", gap: 3, pad: "none", children: [
3528
3517
  Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx5(NumberWidget, { field, controller, component: i }, i)),
3529
- field.expandable && controller.isUniformVector(field.id) && /* @__PURE__ */ jsx5(
3530
- "button",
3531
- {
3532
- type: "button",
3533
- style: S2.miniBtn,
3534
- onClick: () => controller.toggleExpanded(field.id),
3535
- title: "Link axes",
3536
- "aria-label": "Collapse",
3537
- children: "\u22EF"
3538
- }
3539
- )
3518
+ field.expandable && controller.isUniformVector(field.id) ? toggle("Collapse", "Link axes") : null
3540
3519
  ] });
3541
3520
  }
3542
3521
  function TextWidget({ field, controller }) {
@@ -3546,26 +3525,17 @@ function TextWidget({ field, controller }) {
3546
3525
  const shared = {
3547
3526
  value: displayText(field, controller),
3548
3527
  placeholder: mixed ? controller.getMixedPlaceholder() : field.placeholder,
3528
+ mixed,
3549
3529
  readOnly: !editable,
3550
3530
  disabled: field.disabled,
3531
+ label: field.label,
3551
3532
  onFocus: handlers.onFocus,
3552
3533
  onChange: handlers.onChange,
3553
3534
  onBlur: handlers.onBlur,
3554
- onKeyDown: handlers.onKeyDown,
3555
- spellCheck: false,
3556
- "aria-label": field.label
3535
+ onKeyDown: handlers.onKeyDown
3557
3536
  };
3558
- if (field.type === "textarea") {
3559
- return /* @__PURE__ */ jsx5(
3560
- "textarea",
3561
- {
3562
- ...shared,
3563
- rows: field.rows ?? 3,
3564
- style: { ...S2.input, ...S2.textarea, ...mixed ? S2.mixedInput : null }
3565
- }
3566
- );
3567
- }
3568
- return /* @__PURE__ */ jsx5("input", { type: "text", ...shared, style: { ...S2.input, ...mixed ? S2.mixedInput : null } });
3537
+ if (field.type === "textarea") return /* @__PURE__ */ jsx5(TextArea, { ...shared, rows: field.rows ?? 3 });
3538
+ return /* @__PURE__ */ jsx5(Input, { ...shared });
3569
3539
  }
3570
3540
  function CodeWidget({ field, controller }) {
3571
3541
  const editable = isFieldEditable(field);
@@ -3573,15 +3543,17 @@ function CodeWidget({ field, controller }) {
3573
3543
  const handlers = useEditingHandlers(field, controller);
3574
3544
  const expression = field.type === "expression";
3575
3545
  return /* @__PURE__ */ jsx5(
3576
- "textarea",
3546
+ TextArea,
3577
3547
  {
3548
+ variant: "mono",
3578
3549
  value: displayText(field, controller),
3579
3550
  placeholder: mixed ? controller.getMixedPlaceholder() : field.placeholder ?? (expression ? "= expression" : ""),
3551
+ mixed,
3580
3552
  readOnly: !editable,
3581
3553
  disabled: field.disabled,
3582
3554
  rows: field.rows ?? (expression ? 2 : 5),
3583
- spellCheck: false,
3584
- "aria-label": field.label,
3555
+ wrap: expression ? "off" : void 0,
3556
+ label: field.label,
3585
3557
  onFocus: handlers.onFocus,
3586
3558
  onChange: handlers.onChange,
3587
3559
  onBlur: handlers.onBlur,
@@ -3592,21 +3564,10 @@ function CodeWidget({ field, controller }) {
3592
3564
  const { selectionStart: start, selectionEnd: end, value } = el;
3593
3565
  el.value = `${value.slice(0, start)} ${value.slice(end)}`;
3594
3566
  el.selectionStart = el.selectionEnd = start + 2;
3595
- handlers.onChange?.({ currentTarget: el, target: el });
3567
+ handlers.onChange(el.value);
3596
3568
  return;
3597
3569
  }
3598
- handlers.onKeyDown?.(event);
3599
- },
3600
- style: {
3601
- ...S2.input,
3602
- ...S2.textarea,
3603
- fontFamily: "var(--xeno-font-mono)",
3604
- fontSize: 11,
3605
- lineHeight: "16px",
3606
- // An expression is a formula, not prose: never wrap it, so the structure stays readable.
3607
- whiteSpace: expression ? "pre" : "pre-wrap",
3608
- overflowX: expression ? "auto" : "hidden",
3609
- ...mixed ? S2.mixedInput : null
3570
+ handlers.onKeyDown(event);
3610
3571
  }
3611
3572
  }
3612
3573
  );
@@ -3615,29 +3576,7 @@ function BooleanWidget({ field, controller }) {
3615
3576
  const editable = isFieldEditable(field);
3616
3577
  const mixed = isFieldMixed(field);
3617
3578
  const on = controller.getFieldValue(field.id) === true;
3618
- return /* @__PURE__ */ jsx5(
3619
- "button",
3620
- {
3621
- type: "button",
3622
- role: "switch",
3623
- "aria-checked": mixed ? "mixed" : on,
3624
- "aria-label": field.label,
3625
- disabled: !editable,
3626
- onClick: () => controller.setValue(field.id, !on),
3627
- style: { ...S2.toggleTrack, background: on ? "var(--xeno-active)" : "var(--xeno-border)" },
3628
- children: /* @__PURE__ */ jsx5(
3629
- "span",
3630
- {
3631
- style: {
3632
- ...S2.toggleKnob,
3633
- transform: on ? "translateX(10px)" : "translateX(0)",
3634
- borderRadius: on ? 3 : 1,
3635
- opacity: mixed ? 0.4 : 1
3636
- }
3637
- }
3638
- )
3639
- }
3640
- );
3579
+ return /* @__PURE__ */ jsx5(Toggle, { size: "sm", checked: on, mixed, label: field.label, disabled: !editable, onChange: (next) => controller.setValue(field.id, next) });
3641
3580
  }
3642
3581
  function SelectWidget({ field, controller }) {
3643
3582
  const editable = isFieldEditable(field);
@@ -3645,70 +3584,41 @@ function SelectWidget({ field, controller }) {
3645
3584
  const current = controller.getFieldValue(field.id);
3646
3585
  const options = field.options ?? [];
3647
3586
  const value = mixed ? "" : String(current ?? "");
3648
- const hasCurrent = mixed || options.some((o) => o.value === value);
3649
- return /* @__PURE__ */ jsxs4(
3650
- "select",
3651
- {
3652
- value,
3653
- disabled: !editable,
3654
- "aria-label": field.label,
3655
- onChange: (e) => controller.setValue(field.id, e.target.value),
3656
- style: { ...S2.input, ...mixed ? S2.mixedInput : null },
3657
- children: [
3658
- mixed && /* @__PURE__ */ jsx5("option", { value: "", children: controller.getMixedPlaceholder() }),
3659
- !hasCurrent && /* @__PURE__ */ jsx5("option", { value, children: value || "\u2014" }),
3660
- options.map((o) => /* @__PURE__ */ jsx5("option", { value: o.value, disabled: o.disabled, children: o.label }, o.value))
3661
- ]
3662
- }
3663
- );
3587
+ const hasCurrent = mixed || value === "" || options.some((o) => o.value === value);
3588
+ const all = hasCurrent ? options : [{ value, label: value }, ...options];
3589
+ return /* @__PURE__ */ jsx5(Select, { options: all, value, mixed, disabled: !editable, label: field.label, onChange: (next) => controller.setValue(field.id, next) });
3664
3590
  }
3665
3591
  function SegmentedWidget({ field, controller }) {
3666
3592
  const editable = isFieldEditable(field);
3667
3593
  const current = String(controller.getFieldValue(field.id) ?? "");
3668
- return /* @__PURE__ */ jsx5("span", { style: S2.segmented, role: "radiogroup", "aria-label": field.label, children: (field.options ?? []).map((o) => {
3669
- const active = o.value === current;
3670
- return /* @__PURE__ */ jsx5(
3671
- "button",
3672
- {
3673
- type: "button",
3674
- role: "radio",
3675
- "aria-checked": active,
3676
- disabled: !editable || o.disabled,
3677
- onClick: () => controller.setValue(field.id, o.value),
3678
- style: { ...S2.segment, ...active ? S2.segmentActive : null },
3679
- children: o.label
3680
- },
3681
- o.value
3682
- );
3683
- }) });
3594
+ return /* @__PURE__ */ jsx5(
3595
+ SegmentedControl,
3596
+ {
3597
+ size: "sm",
3598
+ stretch: true,
3599
+ options: field.options ?? [],
3600
+ value: current,
3601
+ disabled: !editable,
3602
+ label: field.label,
3603
+ onChange: (next) => controller.setValue(field.id, next)
3604
+ }
3605
+ );
3684
3606
  }
3685
3607
  function ColorWidget({ field, controller }) {
3686
3608
  const mixed = isFieldMixed(field);
3687
3609
  const raw = controller.getFieldValue(field.id);
3688
3610
  const hex = typeof raw === "string" ? raw : typeof raw?.hex === "string" ? raw.hex : "";
3689
3611
  const editable = isFieldEditable(field);
3690
- return /* @__PURE__ */ jsxs4(
3691
- "button",
3612
+ return /* @__PURE__ */ jsx5(
3613
+ Swatch,
3692
3614
  {
3693
- type: "button",
3694
- style: S2.colorCell,
3615
+ color: hex || void 0,
3616
+ text: mixed ? controller.getMixedPlaceholder() : hex || "\u2014",
3617
+ mixed,
3695
3618
  disabled: !editable,
3696
3619
  onClick: () => controller.requestColorEditor(field.id),
3697
3620
  title: "Edit in the Color panel",
3698
- "aria-label": `${field.label}: ${mixed ? "mixed" : hex || "none"}`,
3699
- children: [
3700
- /* @__PURE__ */ jsx5(
3701
- "span",
3702
- {
3703
- style: {
3704
- ...S2.swatch,
3705
- background: mixed || !hex ? "transparent" : hex,
3706
- border: mixed || !hex ? "1px solid var(--xeno-control)" : "1px solid var(--xeno-control)"
3707
- }
3708
- }
3709
- ),
3710
- /* @__PURE__ */ jsx5("span", { style: { ...S2.colorText, ...mixed ? S2.mixedInput : null }, children: mixed ? controller.getMixedPlaceholder() : hex || "\u2014" })
3711
- ]
3621
+ label: `${field.label}: ${mixed ? "mixed" : hex || "none"}`
3712
3622
  }
3713
3623
  );
3714
3624
  }
@@ -3717,77 +3627,43 @@ function ListWidget({ field, controller }) {
3717
3627
  const raw = controller.getFieldValue(field.id);
3718
3628
  const items = Array.isArray(raw) ? raw : [];
3719
3629
  const write = (next) => void controller.setValue(field.id, next);
3720
- return /* @__PURE__ */ jsxs4("span", { style: S2.list, children: [
3721
- items.map((item, i) => /* @__PURE__ */ jsxs4("span", { style: S2.listRow, children: [
3722
- /* @__PURE__ */ jsx5("span", { style: S2.listLabel, children: typeof item === "string" ? item : JSON.stringify(item) }),
3723
- editable && /* @__PURE__ */ jsxs4(Fragment, { children: [
3724
- /* @__PURE__ */ jsx5(
3725
- "button",
3726
- {
3727
- type: "button",
3728
- style: S2.miniBtn,
3729
- disabled: i === 0,
3730
- onClick: () => {
3731
- const next = [...items];
3732
- const [moved] = next.splice(i, 1);
3733
- next.splice(i - 1, 0, moved);
3734
- write(next);
3735
- },
3736
- "aria-label": "Move up",
3737
- children: "\u2191"
3738
- }
3739
- ),
3740
- /* @__PURE__ */ jsx5(
3741
- "button",
3742
- {
3743
- type: "button",
3744
- style: S2.miniBtn,
3745
- disabled: i === items.length - 1,
3746
- onClick: () => {
3747
- const next = [...items];
3748
- const [moved] = next.splice(i, 1);
3749
- next.splice(i + 1, 0, moved);
3750
- write(next);
3751
- },
3752
- "aria-label": "Move down",
3753
- children: "\u2193"
3754
- }
3755
- ),
3756
- /* @__PURE__ */ jsx5(
3757
- "button",
3758
- {
3759
- type: "button",
3760
- style: S2.miniBtn,
3761
- onClick: () => write(items.filter((_, j) => j !== i)),
3762
- "aria-label": "Remove",
3763
- children: /* @__PURE__ */ jsx5(XIcon, {})
3764
- }
3765
- )
3766
- ] })
3630
+ const move = (i, to) => {
3631
+ const next = [...items];
3632
+ const [moved] = next.splice(i, 1);
3633
+ next.splice(to, 0, moved);
3634
+ write(next);
3635
+ };
3636
+ return /* @__PURE__ */ jsxs4(Stack, { gap: 2, pad: "none", children: [
3637
+ items.map((item, i) => /* @__PURE__ */ jsxs4(Stack, { direction: "row", gap: 2, pad: "none", children: [
3638
+ /* @__PURE__ */ jsx5(Text, { role: "meta", children: typeof item === "string" ? item : JSON.stringify(item) }),
3639
+ editable ? /* @__PURE__ */ jsxs4(Fragment, { children: [
3640
+ /* @__PURE__ */ jsx5(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\u2191" }), label: "Move up", disabled: i === 0, onClick: () => move(i, i - 1) }),
3641
+ /* @__PURE__ */ jsx5(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: "\u2193" }), label: "Move down", disabled: i === items.length - 1, onClick: () => move(i, i + 1) }),
3642
+ /* @__PURE__ */ jsx5(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx5(XIcon, {}), label: "Remove", onClick: () => write(items.filter((_, j) => j !== i)) })
3643
+ ] }) : null
3767
3644
  ] }, i)),
3768
- editable && /* @__PURE__ */ jsx5("button", { type: "button", style: S2.textBtn, onClick: () => write([...items, ""]), children: "+ Add" })
3645
+ editable ? /* @__PURE__ */ jsx5(TextButton, { onClick: () => write([...items, ""]), children: "+ Add" }) : null
3769
3646
  ] });
3770
3647
  }
3771
3648
  function InfoWidget({ field, controller }) {
3772
3649
  const value = controller.getFieldValue(field.id);
3773
- return /* @__PURE__ */ jsx5("span", { style: S2.infoValue, children: value === void 0 || value === null ? "\u2014" : String(value) });
3650
+ return /* @__PURE__ */ jsx5(Text, { role: "meta", children: value === void 0 || value === null ? "\u2014" : String(value) });
3774
3651
  }
3775
3652
  function JsonWidget({ field, controller }) {
3776
3653
  const editable = isFieldEditable(field);
3777
3654
  const handlers = useEditingHandlers(field, controller);
3778
3655
  return /* @__PURE__ */ jsx5(
3779
- "textarea",
3656
+ TextArea,
3780
3657
  {
3658
+ variant: "mono",
3781
3659
  value: displayText(field, controller),
3782
3660
  readOnly: !editable,
3783
3661
  rows: field.rows ?? 2,
3662
+ label: field.label,
3784
3663
  onFocus: handlers.onFocus,
3785
3664
  onChange: handlers.onChange,
3786
3665
  onBlur: handlers.onBlur,
3787
- onKeyDown: handlers.onKeyDown,
3788
- spellCheck: false,
3789
- "aria-label": field.label,
3790
- style: { ...S2.input, ...S2.textarea, ...S2.mono }
3666
+ onKeyDown: handlers.onKeyDown
3791
3667
  }
3792
3668
  );
3793
3669
  }
@@ -9790,14 +9666,14 @@ import { useSyncExternalStore as useSyncExternalStore7 } from "react";
9790
9666
  import {
9791
9667
  Badge as Badge2,
9792
9668
  EmptyState as EmptyState2,
9793
- IconButton,
9669
+ IconButton as IconButton2,
9794
9670
  Row,
9795
9671
  RowList,
9796
9672
  ScrollArea,
9797
9673
  SearchField,
9798
9674
  Section,
9799
9675
  StatusBar as StatusBar3,
9800
- TextButton,
9676
+ TextButton as TextButton2,
9801
9677
  Toolbar as Toolbar2,
9802
9678
  ToolbarGroup as ToolbarGroup2
9803
9679
  } from "@xenosystem/components/chrome";
@@ -9907,7 +9783,7 @@ function FindPanelView({
9907
9783
  ),
9908
9784
  right: /* @__PURE__ */ jsxs11(ToolbarGroup2, { end: true, children: [
9909
9785
  /* @__PURE__ */ jsx12(
9910
- IconButton,
9786
+ IconButton2,
9911
9787
  {
9912
9788
  label: "Match case",
9913
9789
  active: state.options.caseSensitive,
@@ -9916,7 +9792,7 @@ function FindPanelView({
9916
9792
  }
9917
9793
  ),
9918
9794
  /* @__PURE__ */ jsx12(
9919
- IconButton,
9795
+ IconButton2,
9920
9796
  {
9921
9797
  label: "Whole word",
9922
9798
  active: state.options.wholeWord,
@@ -9925,7 +9801,7 @@ function FindPanelView({
9925
9801
  }
9926
9802
  ),
9927
9803
  /* @__PURE__ */ jsx12(
9928
- IconButton,
9804
+ IconButton2,
9929
9805
  {
9930
9806
  label: "Regular expression",
9931
9807
  active: state.options.regex,
@@ -9953,7 +9829,7 @@ function FindPanelView({
9953
9829
  ),
9954
9830
  right: /* @__PURE__ */ jsxs11(ToolbarGroup2, { end: true, children: [
9955
9831
  /* @__PURE__ */ jsx12(
9956
- IconButton,
9832
+ IconButton2,
9957
9833
  {
9958
9834
  label: "Previous match",
9959
9835
  disabled: state.matches.length === 0,
@@ -9962,7 +9838,7 @@ function FindPanelView({
9962
9838
  }
9963
9839
  ),
9964
9840
  /* @__PURE__ */ jsx12(
9965
- IconButton,
9841
+ IconButton2,
9966
9842
  {
9967
9843
  label: "Next match",
9968
9844
  disabled: state.matches.length === 0,
@@ -9970,7 +9846,7 @@ function FindPanelView({
9970
9846
  icon: /* @__PURE__ */ jsx12(DownIcon, {})
9971
9847
  }
9972
9848
  ),
9973
- /* @__PURE__ */ jsx12(TextButton, { onClick: () => controller.setReplaceVisible(!state.replaceVisible), children: state.replaceVisible ? "Hide replace" : "Replace" })
9849
+ /* @__PURE__ */ jsx12(TextButton2, { onClick: () => controller.setReplaceVisible(!state.replaceVisible), children: state.replaceVisible ? "Hide replace" : "Replace" })
9974
9850
  ] })
9975
9851
  }
9976
9852
  ),
@@ -9987,8 +9863,8 @@ function FindPanelView({
9987
9863
  }
9988
9864
  ),
9989
9865
  right: /* @__PURE__ */ jsxs11(ToolbarGroup2, { end: true, children: [
9990
- /* @__PURE__ */ jsx12(TextButton, { disabled: !state.canReplace, onClick: () => controller.replaceCurrent(), children: "Replace" }),
9991
- /* @__PURE__ */ jsxs11(TextButton, { disabled: !state.canReplace, onClick: () => controller.replaceAll(), children: [
9866
+ /* @__PURE__ */ jsx12(TextButton2, { disabled: !state.canReplace, onClick: () => controller.replaceCurrent(), children: "Replace" }),
9867
+ /* @__PURE__ */ jsxs11(TextButton2, { disabled: !state.canReplace, onClick: () => controller.replaceAll(), children: [
9992
9868
  "All (",
9993
9869
  state.matches.length,
9994
9870
  ")"
@@ -10667,9 +10543,9 @@ import {
10667
10543
  EmptyState as EmptyState3,
10668
10544
  ScrollArea as ScrollArea2,
10669
10545
  Section as Section2,
10670
- SegmentedControl,
10546
+ SegmentedControl as SegmentedControl2,
10671
10547
  StatusBar as StatusBar4,
10672
- TextButton as TextButton2,
10548
+ TextButton as TextButton3,
10673
10549
  Toolbar as Toolbar3,
10674
10550
  ToolbarGroup as ToolbarGroup3
10675
10551
  } from "@xenosystem/components/chrome";
@@ -10749,7 +10625,7 @@ function ThreadCard({
10749
10625
  /* @__PURE__ */ jsx13("p", { style: { fontSize: 11, opacity: 0.75, margin: 0, whiteSpace: "pre-wrap" }, children: message.body })
10750
10626
  ] }, message.id)),
10751
10627
  allowReactions && thread.reactions?.length ? /* @__PURE__ */ jsx13("div", { style: { display: "flex", gap: 4 }, children: thread.reactions.map((reaction) => /* @__PURE__ */ jsxs12(
10752
- TextButton2,
10628
+ TextButton3,
10753
10629
  {
10754
10630
  onClick: () => controller.react(
10755
10631
  thread.id,
@@ -10792,11 +10668,11 @@ function ThreadCard({
10792
10668
  }
10793
10669
  }
10794
10670
  ),
10795
- /* @__PURE__ */ jsx13(TextButton2, { onClick: () => controller.reply(thread.id), children: "Send" })
10671
+ /* @__PURE__ */ jsx13(TextButton3, { onClick: () => controller.reply(thread.id), children: "Send" })
10796
10672
  ] }) : /* @__PURE__ */ jsxs12("div", { style: { display: "flex", gap: 6 }, children: [
10797
- /* @__PURE__ */ jsx13(TextButton2, { onClick: () => controller.setReplyingTo(thread.id), children: "Reply" }),
10798
- /* @__PURE__ */ jsx13(TextButton2, { onClick: () => controller.resolve(thread.id, !thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
10799
- /* @__PURE__ */ jsx13(TextButton2, { onClick: () => controller.remove(thread.id), children: "Delete" })
10673
+ /* @__PURE__ */ jsx13(TextButton3, { onClick: () => controller.setReplyingTo(thread.id), children: "Reply" }),
10674
+ /* @__PURE__ */ jsx13(TextButton3, { onClick: () => controller.resolve(thread.id, !thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
10675
+ /* @__PURE__ */ jsx13(TextButton3, { onClick: () => controller.remove(thread.id), children: "Delete" })
10800
10676
  ] })
10801
10677
  ] })
10802
10678
  }
@@ -10817,7 +10693,7 @@ function CommentsPanelView({
10817
10693
  Toolbar3,
10818
10694
  {
10819
10695
  left: /* @__PURE__ */ jsx13(
10820
- SegmentedControl,
10696
+ SegmentedControl2,
10821
10697
  {
10822
10698
  label: "Show",
10823
10699
  value: state.filter.show ?? "open",
@@ -10830,7 +10706,7 @@ function CommentsPanelView({
10830
10706
  }
10831
10707
  ),
10832
10708
  right: /* @__PURE__ */ jsx13(ToolbarGroup3, { end: true, children: /* @__PURE__ */ jsx13(
10833
- SegmentedControl,
10709
+ SegmentedControl2,
10834
10710
  {
10835
10711
  label: "Sort",
10836
10712
  value: state.sort,
@@ -10851,7 +10727,7 @@ function CommentsPanelView({
10851
10727
  " lost the content",
10852
10728
  state.totals.orphaned === 1 ? " it was" : " they were",
10853
10729
  " about.",
10854
- state.filter.includeOrphaned === false ? /* @__PURE__ */ jsx13(TextButton2, { onClick: () => controller.setFilter({ includeOrphaned: true }), children: "Show" }) : null
10730
+ state.filter.includeOrphaned === false ? /* @__PURE__ */ jsx13(TextButton3, { onClick: () => controller.setFilter({ includeOrphaned: true }), children: "Show" }) : null
10855
10731
  ] }) : null,
10856
10732
  /* @__PURE__ */ jsx13(ScrollArea2, { children: state.threads.length === 0 ? state.filteredEmpty ? (
10857
10733
  // NOT "no comments". There are comments; this filter hides them, and telling a
@@ -10921,7 +10797,7 @@ function CommentsPanelView({
10921
10797
  }
10922
10798
  ),
10923
10799
  /* @__PURE__ */ jsx13("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 2 }, children: /* @__PURE__ */ jsx13(
10924
- TextButton2,
10800
+ TextButton3,
10925
10801
  {
10926
10802
  strong: true,
10927
10803
  disabled: state.activeAnchor === null || state.draft.trim() === "",
@@ -13635,7 +13511,7 @@ import {
13635
13511
  Badge as Badge4,
13636
13512
  EmptyState as EmptyState5,
13637
13513
  ErrorState,
13638
- IconButton as IconButton2,
13514
+ IconButton as IconButton3,
13639
13515
  LoadingState,
13640
13516
  Row as Row2,
13641
13517
  ScrollArea as ScrollArea3,
@@ -13851,16 +13727,16 @@ function TreePanelView({
13851
13727
  }
13852
13728
  ) : void 0,
13853
13729
  right: /* @__PURE__ */ jsxs15(ToolbarGroup5, { end: true, children: [
13854
- /* @__PURE__ */ jsx16(IconButton2, { icon: /* @__PURE__ */ jsx16(ExpandGlyph, {}), label: "Expand all", onClick: () => controller.expandAll() }),
13730
+ /* @__PURE__ */ jsx16(IconButton3, { icon: /* @__PURE__ */ jsx16(ExpandGlyph, {}), label: "Expand all", onClick: () => controller.expandAll() }),
13855
13731
  /* @__PURE__ */ jsx16(
13856
- IconButton2,
13732
+ IconButton3,
13857
13733
  {
13858
13734
  icon: /* @__PURE__ */ jsx16(CollapseGlyph, {}),
13859
13735
  label: "Collapse all",
13860
13736
  onClick: () => controller.collapseAll()
13861
13737
  }
13862
13738
  ),
13863
- /* @__PURE__ */ jsx16(IconButton2, { icon: /* @__PURE__ */ jsx16(RefreshGlyph, {}), label: "Refresh", onClick: () => controller.refresh() })
13739
+ /* @__PURE__ */ jsx16(IconButton3, { icon: /* @__PURE__ */ jsx16(RefreshGlyph, {}), label: "Refresh", onClick: () => controller.refresh() })
13864
13740
  ] })
13865
13741
  }
13866
13742
  ),
@@ -13998,7 +13874,7 @@ function TreeRowView({
13998
13874
  /* @__PURE__ */ jsx16(Badge4, { tone: badge.tone, className: badge.title ? void 0 : void 0, children: badge.text }, badge.id)
13999
13875
  )),
14000
13876
  node.actions?.map((action) => /* @__PURE__ */ jsx16(
14001
- IconButton2,
13877
+ IconButton3,
14002
13878
  {
14003
13879
  size: "sm",
14004
13880
  icon: /* @__PURE__ */ jsx16(NodeIcon, { icon: action.icon }),
@@ -780,6 +780,7 @@ function ticksPerStep(unit, timebase) {
780
780
 
781
781
  // src/time/transport/react/TransportPanelView.tsx
782
782
  import { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
783
+ import { Column, IconButton, NumberInput, Readout, Slider, Stack, TextButton } from "@xenosystem/components/chrome";
783
784
 
784
785
  // src/time/transport/react/icons.tsx
785
786
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -928,9 +929,8 @@ function TransportPanelView({ controller }) {
928
929
  [controller]
929
930
  );
930
931
  return /* @__PURE__ */ jsxs2(
931
- "div",
932
+ Column,
932
933
  {
933
- style: S.root,
934
934
  className: "xeno-transport-panel",
935
935
  onKeyDown,
936
936
  onKeyUp,
@@ -938,228 +938,66 @@ function TransportPanelView({ controller }) {
938
938
  role: "group",
939
939
  "aria-label": "Transport",
940
940
  children: [
941
- /* @__PURE__ */ jsxs2("div", { style: S.row, children: [
942
- /* @__PURE__ */ jsx2("button", { type: "button", style: S.iconBtn, onClick: () => controller.goToStart(), title: "Go to start", "aria-label": "Go to start", children: /* @__PURE__ */ jsx2(StartIcon, {}) }),
943
- /* @__PURE__ */ jsx2("button", { type: "button", style: S.iconBtn, onClick: () => controller.step(-1), title: "Step back", "aria-label": "Step back", children: /* @__PURE__ */ jsx2(StepBackIcon, {}) }),
944
- controller.showsControl("shuttle") && /* @__PURE__ */ jsx2("button", { type: "button", style: S.iconBtn, onClick: () => controller.shuttleStep(-1), title: "Shuttle reverse (J)", "aria-label": "Shuttle reverse", children: /* @__PURE__ */ jsx2(ShuttleLeftIcon, {}) }),
941
+ /* @__PURE__ */ jsxs2(Stack, { direction: "row", gap: 3, pad: "gutter", children: [
942
+ /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(StartIcon, {}), label: "Go to start", onClick: () => controller.goToStart() }),
943
+ /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(StepBackIcon, {}), label: "Step back", onClick: () => controller.step(-1) }),
944
+ controller.showsControl("shuttle") && /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(ShuttleLeftIcon, {}), label: "Shuttle reverse (J)", onClick: () => controller.shuttleStep(-1) }),
945
945
  /* @__PURE__ */ jsx2(
946
- "button",
947
- {
948
- type: "button",
949
- style: { ...S.iconBtn, ...S.primaryBtn },
950
- onClick: () => controller.togglePlay(),
951
- title: playing ? "Pause (Space)" : "Play (Space)",
952
- "aria-label": playing ? "Pause" : "Play",
953
- "aria-pressed": playing,
954
- children: playing ? /* @__PURE__ */ jsx2(PauseIcon, {}) : /* @__PURE__ */ jsx2(PlayIcon, {})
955
- }
956
- ),
957
- /* @__PURE__ */ jsx2("button", { type: "button", style: S.iconBtn, onClick: () => controller.stop(), title: "Stop", "aria-label": "Stop", children: /* @__PURE__ */ jsx2(StopIcon, {}) }),
958
- controller.showsControl("shuttle") && /* @__PURE__ */ jsx2("button", { type: "button", style: S.iconBtn, onClick: () => controller.shuttleStep(1), title: "Shuttle forward (L)", "aria-label": "Shuttle forward", children: /* @__PURE__ */ jsx2(ShuttleRightIcon, {}) }),
959
- /* @__PURE__ */ jsx2("button", { type: "button", style: S.iconBtn, onClick: () => controller.step(1), title: "Step forward", "aria-label": "Step forward", children: /* @__PURE__ */ jsx2(StepForwardIcon, {}) }),
960
- /* @__PURE__ */ jsx2("button", { type: "button", style: S.iconBtn, onClick: () => controller.goToEnd(), title: "Go to end", "aria-label": "Go to end", children: /* @__PURE__ */ jsx2(EndIcon, {}) }),
961
- controller.showsControl("record") && /* @__PURE__ */ jsx2(
962
- "button",
946
+ IconButton,
963
947
  {
964
- type: "button",
965
- style: { ...S.iconBtn, color: state.recording ? "var(--xeno-danger)" : void 0, opacity: state.recording ? 1 : 0.7 },
966
- onClick: () => controller.record(),
967
- title: "Record",
968
- "aria-label": "Record",
969
- "aria-pressed": !!state.recording,
970
- children: /* @__PURE__ */ jsx2(RecordIcon, {})
948
+ size: "sm",
949
+ variant: "primary",
950
+ icon: playing ? /* @__PURE__ */ jsx2(PauseIcon, {}) : /* @__PURE__ */ jsx2(PlayIcon, {}),
951
+ label: playing ? "Pause (Space)" : "Play (Space)",
952
+ active: playing,
953
+ onClick: () => controller.togglePlay()
971
954
  }
972
955
  ),
973
- controller.showsControl("loop") && /* @__PURE__ */ jsx2(
974
- "button",
975
- {
976
- type: "button",
977
- style: { ...S.iconBtn, opacity: state.loopEnabled ? 1 : 0.4 },
978
- onClick: () => controller.toggleLoop(),
979
- title: "Loop",
980
- "aria-label": "Loop",
981
- "aria-pressed": !!state.loopEnabled,
982
- children: /* @__PURE__ */ jsx2(LoopIcon, {})
983
- }
984
- ),
985
- controller.showsControl("metronome") && /* @__PURE__ */ jsx2(
986
- "button",
987
- {
988
- type: "button",
989
- style: { ...S.iconBtn, opacity: state.metronome ? 1 : 0.4 },
990
- onClick: () => controller.toggleMetronome(),
991
- title: "Metronome",
992
- "aria-label": "Metronome",
993
- "aria-pressed": !!state.metronome,
994
- children: /* @__PURE__ */ jsx2(MetronomeIcon, {})
995
- }
996
- ),
997
- controller.showsControl("punch") && /* @__PURE__ */ jsx2("button", { type: "button", style: { ...S.chipBtn, opacity: state.punch ? 1 : 0.4 }, "aria-pressed": !!state.punch, title: "Punch", children: "PUNCH" }),
998
- /* @__PURE__ */ jsxs2(
999
- "button",
956
+ /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(StopIcon, {}), label: "Stop", onClick: () => controller.stop() }),
957
+ controller.showsControl("shuttle") && /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(ShuttleRightIcon, {}), label: "Shuttle forward (L)", onClick: () => controller.shuttleStep(1) }),
958
+ /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(StepForwardIcon, {}), label: "Step forward", onClick: () => controller.step(1) }),
959
+ /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(EndIcon, {}), label: "Go to end", onClick: () => controller.goToEnd() }),
960
+ controller.showsControl("record") && /* @__PURE__ */ jsx2(IconButton, { size: "sm", variant: "danger", icon: /* @__PURE__ */ jsx2(RecordIcon, {}), label: "Record", active: !!state.recording, onClick: () => controller.record() }),
961
+ controller.showsControl("loop") && /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(LoopIcon, {}), label: "Loop", active: !!state.loopEnabled, onClick: () => controller.toggleLoop() }),
962
+ controller.showsControl("metronome") && /* @__PURE__ */ jsx2(IconButton, { size: "sm", icon: /* @__PURE__ */ jsx2(MetronomeIcon, {}), label: "Metronome", active: !!state.metronome, onClick: () => controller.toggleMetronome() }),
963
+ controller.showsControl("punch") && /* @__PURE__ */ jsx2(TextButton, { strong: !!state.punch, children: "PUNCH" }),
964
+ /* @__PURE__ */ jsx2(
965
+ Readout,
1000
966
  {
1001
- type: "button",
1002
- style: S.readout,
1003
- onClick: () => controller.cycleDisplay(),
967
+ value: controller.getReadout(),
968
+ unit: (0, format_exports.displayLabel)(controller.getDisplay()),
969
+ label: `Position ${controller.getReadout()}`,
1004
970
  title: "Click to change time display",
1005
- "aria-label": `Position ${controller.getReadout()}`,
1006
- children: [
1007
- /* @__PURE__ */ jsx2("span", { style: S.readoutValue, children: controller.getReadout() }),
1008
- /* @__PURE__ */ jsx2("span", { style: S.readoutUnit, children: (0, format_exports.displayLabel)(controller.getDisplay()) })
1009
- ]
971
+ onClick: () => controller.cycleDisplay()
1010
972
  }
1011
973
  ),
1012
- /* @__PURE__ */ jsx2("span", { style: S.duration, children: controller.getDurationReadout() }),
1013
- controller.showsControl("bpm") && /* @__PURE__ */ jsxs2("label", { style: S.bpm, children: [
1014
- /* @__PURE__ */ jsx2("span", { style: S.bpmLabel, children: "BPM" }),
1015
- /* @__PURE__ */ jsx2(
1016
- "input",
1017
- {
1018
- type: "number",
1019
- value: state.bpm ?? 120,
1020
- onChange: (e) => controller.setTempo(Number(e.target.value)),
1021
- style: S.bpmInput,
1022
- "aria-label": "Tempo"
1023
- }
1024
- )
1025
- ] }),
1026
- controller.showsControl("inOut") && /* @__PURE__ */ jsxs2("span", { style: S.inOut, children: [
1027
- /* @__PURE__ */ jsx2("button", { type: "button", style: S.chipBtn, onClick: () => controller.setInPoint(), title: "Set in point", children: "IN" }),
1028
- /* @__PURE__ */ jsx2("button", { type: "button", style: S.chipBtn, onClick: () => controller.setOutPoint(), title: "Set out point", children: "OUT" })
974
+ /* @__PURE__ */ jsx2(Readout, { size: "sm", value: controller.getDurationReadout() }),
975
+ controller.showsControl("bpm") && /* @__PURE__ */ jsx2(NumberInput, { caption: "BPM", label: "Tempo", value: state.bpm ?? 120, onChange: (bpm) => controller.setTempo(bpm) }),
976
+ controller.showsControl("inOut") && /* @__PURE__ */ jsxs2(Stack, { direction: "row", gap: 2, pad: "none", children: [
977
+ /* @__PURE__ */ jsx2(TextButton, { onClick: () => controller.setInPoint(), children: "IN" }),
978
+ /* @__PURE__ */ jsx2(TextButton, { onClick: () => controller.setOutPoint(), children: "OUT" })
1029
979
  ] })
1030
980
  ] }),
1031
- controller.showsControl("scrubber") && /* @__PURE__ */ jsxs2(
1032
- "div",
981
+ controller.showsControl("scrubber") && /* @__PURE__ */ jsx2(
982
+ Slider,
1033
983
  {
1034
- ref: scrubRef,
1035
- style: S.scrubTrack,
984
+ trackRef: scrubRef,
985
+ progress: controller.getProgress(),
986
+ label: "Playhead",
987
+ valueMin: 0,
988
+ valueMax: controller.getDuration(),
989
+ valueNow: controller.getCurrentTick(),
990
+ valueText: controller.getReadout(),
1036
991
  onPointerDown: onScrubDown,
1037
992
  onPointerMove: onScrubMove,
1038
993
  onPointerUp: onScrubUp,
1039
- onPointerCancel: () => controller.cancelScrub(),
1040
- role: "slider",
1041
- "aria-label": "Playhead",
1042
- "aria-valuemin": 0,
1043
- "aria-valuemax": controller.getDuration(),
1044
- "aria-valuenow": controller.getCurrentTick(),
1045
- "aria-valuetext": controller.getReadout(),
1046
- tabIndex: 0,
1047
- children: [
1048
- /* @__PURE__ */ jsx2("span", { style: { ...S.scrubFill, width: `${controller.getProgress() * 100}%` } }),
1049
- /* @__PURE__ */ jsx2("span", { style: { ...S.scrubKnob, left: `${controller.getProgress() * 100}%` } })
1050
- ]
994
+ onPointerCancel: () => controller.cancelScrub()
1051
995
  }
1052
996
  )
1053
997
  ]
1054
998
  }
1055
999
  );
1056
1000
  }
1057
- var S = {
1058
- root: {
1059
- display: "flex",
1060
- flexDirection: "column",
1061
- gap: 3,
1062
- padding: "4px 6px",
1063
- fontSize: 11,
1064
- color: "var(--xeno-text)",
1065
- background: "var(--xeno-canvas)",
1066
- userSelect: "none",
1067
- outline: "none"
1068
- },
1069
- row: { display: "flex", alignItems: "center", gap: 3, flexWrap: "wrap" },
1070
- iconBtn: {
1071
- display: "flex",
1072
- alignItems: "center",
1073
- justifyContent: "center",
1074
- width: 20,
1075
- height: 18,
1076
- padding: 0,
1077
- border: "none",
1078
- borderRadius: 2,
1079
- background: "var(--xeno-border-subtle)",
1080
- color: "inherit",
1081
- cursor: "pointer",
1082
- flex: "0 0 auto"
1083
- },
1084
- primaryBtn: { background: "var(--xeno-control)", width: 26 },
1085
- chipBtn: {
1086
- height: 18,
1087
- padding: "0 5px",
1088
- border: "none",
1089
- borderRadius: 2,
1090
- background: "var(--xeno-border-subtle)",
1091
- color: "inherit",
1092
- cursor: "pointer",
1093
- fontSize: 9,
1094
- letterSpacing: "0.05em",
1095
- flex: "0 0 auto"
1096
- },
1097
- readout: {
1098
- display: "flex",
1099
- alignItems: "baseline",
1100
- gap: 4,
1101
- height: 18,
1102
- padding: "0 6px",
1103
- marginLeft: 4,
1104
- border: "1px solid var(--xeno-border)",
1105
- borderRadius: 2,
1106
- background: "var(--xeno-canvas)",
1107
- color: "inherit",
1108
- cursor: "pointer",
1109
- flex: "0 0 auto"
1110
- },
1111
- readoutValue: { fontVariantNumeric: "tabular-nums", fontSize: 12, letterSpacing: "0.02em" },
1112
- readoutUnit: { fontSize: 8, color: "var(--xeno-muted)", letterSpacing: "0.06em" },
1113
- duration: {
1114
- fontVariantNumeric: "tabular-nums",
1115
- fontSize: 10,
1116
- color: "var(--xeno-muted)",
1117
- flex: "0 0 auto"
1118
- },
1119
- bpm: { display: "flex", alignItems: "center", gap: 3, flex: "0 0 auto" },
1120
- bpmLabel: { fontSize: 8, color: "var(--xeno-muted)", letterSpacing: "0.06em" },
1121
- bpmInput: {
1122
- width: 42,
1123
- height: 18,
1124
- background: "var(--xeno-canvas)",
1125
- color: "inherit",
1126
- border: "1px solid var(--xeno-border)",
1127
- borderRadius: 2,
1128
- fontSize: 11,
1129
- padding: "0 4px",
1130
- outline: "none",
1131
- fontVariantNumeric: "tabular-nums"
1132
- },
1133
- inOut: { display: "flex", gap: 2, flex: "0 0 auto" },
1134
- scrubTrack: {
1135
- position: "relative",
1136
- height: 8,
1137
- borderRadius: 2,
1138
- background: "var(--xeno-border-subtle)",
1139
- cursor: "pointer",
1140
- touchAction: "none",
1141
- outline: "none"
1142
- },
1143
- scrubFill: {
1144
- position: "absolute",
1145
- left: 0,
1146
- top: 0,
1147
- bottom: 0,
1148
- background: "var(--xeno-control)",
1149
- borderRadius: 2,
1150
- pointerEvents: "none"
1151
- },
1152
- scrubKnob: {
1153
- position: "absolute",
1154
- top: -1,
1155
- width: 3,
1156
- height: 10,
1157
- marginLeft: -1,
1158
- background: "var(--xeno-text)",
1159
- borderRadius: 1,
1160
- pointerEvents: "none"
1161
- }
1162
- };
1163
1001
 
1164
1002
  // src/time/transport/panel.ts
1165
1003
  function createTransportPanel(options = {}) {
@@ -4177,13 +4015,13 @@ import {
4177
4015
  Badge,
4178
4016
  EmptyState as EmptyState2,
4179
4017
  ErrorState,
4180
- IconButton,
4018
+ IconButton as IconButton2,
4181
4019
  Row,
4182
4020
  RowList,
4183
4021
  ScrollArea,
4184
4022
  SegmentedControl,
4185
4023
  StatusBar as StatusBar2,
4186
- TextButton,
4024
+ TextButton as TextButton2,
4187
4025
  Toolbar as Toolbar2,
4188
4026
  ToolbarGroup as ToolbarGroup2
4189
4027
  } from "@xenosystem/components/chrome";
@@ -4222,7 +4060,7 @@ function CalendarPanelView({
4222
4060
  {
4223
4061
  left: /* @__PURE__ */ jsxs4(Fragment, { children: [
4224
4062
  /* @__PURE__ */ jsx5(
4225
- IconButton,
4063
+ IconButton2,
4226
4064
  {
4227
4065
  icon: /* @__PURE__ */ jsx5(ChevronGlyph, { direction: "left" }),
4228
4066
  label: "Previous",
@@ -4230,14 +4068,14 @@ function CalendarPanelView({
4230
4068
  }
4231
4069
  ),
4232
4070
  /* @__PURE__ */ jsx5(
4233
- IconButton,
4071
+ IconButton2,
4234
4072
  {
4235
4073
  icon: /* @__PURE__ */ jsx5(ChevronGlyph, { direction: "right" }),
4236
4074
  label: "Next",
4237
4075
  onClick: () => controller.navigate(1)
4238
4076
  }
4239
4077
  ),
4240
- /* @__PURE__ */ jsx5(TextButton, { onClick: () => controller.goToToday(), children: "Today" }),
4078
+ /* @__PURE__ */ jsx5(TextButton2, { onClick: () => controller.goToToday(), children: "Today" }),
4241
4079
  /* @__PURE__ */ jsx5("span", { style: { fontSize: 11, opacity: 0.8 }, children: controller.anchorKey().slice(0, 7) })
4242
4080
  ] }),
4243
4081
  right: /* @__PURE__ */ jsxs4(ToolbarGroup2, { end: true, children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenosystem/blocks",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "description": "XENO Blocks — rung 3 of the front ladder: components composed into a contract-bearing unit (manifest: ports, intents, commands, agent surface), rendered by @xenosystem/workbench. ONE package, one subpath per family (/auth, /edit, /data, /time, /ops, /trust, /agent), one named export per block — XENO PACKAGE NAMING - STANDARD.md.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -60,7 +60,7 @@
60
60
  "peerDependencies": {
61
61
  "@duckdb/duckdb-wasm": ">=1.28.0",
62
62
  "@xenosystem/block-sdk": "^0.3.0",
63
- "@xenosystem/components": ">=0.9.3 <1",
63
+ "@xenosystem/components": ">=0.11.2 <1",
64
64
  "@xenosystem/data-core": "^0.1.0",
65
65
  "@xenosystem/elements-react": ">=0.0.1",
66
66
  "@xenosystem/time-core": "^0.1.0",
@@ -76,7 +76,7 @@
76
76
  "@types/react": "^19.0.0",
77
77
  "@types/react-dom": "^19.0.0",
78
78
  "@xenosystem/block-sdk": "^0.3.1",
79
- "@xenosystem/components": "^0.9.3",
79
+ "@xenosystem/components": "^0.11.2",
80
80
  "@xenosystem/data-core": "^0.1.0",
81
81
  "@xenosystem/elements-react": "0.0.1",
82
82
  "@xenosystem/time-core": "^0.1.0",