@synopackageland/ui 0.25.18 → 0.25.19

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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.25.19 (2026-11-14)
6
+
7
+ ### Button
8
+
9
+ - **A button label is never cut with an ellipsis; it wraps instead.** Button keeps its label's width in a flex row (`shrink-0`, was `min-w-0`) and is never wider than its container; only a label wider than the container wraps, centred, and the size is now a minimum height with block padding (`min-h-*` and `py-*`, was `h-*`). SplitButton, NewItemsPill, the phone bar's text action and the phone FAB's pills wrap the same way. The rule is [button-policy](docs/button-policy.md) rule 13, checked in a browser by `pnpm check:button-wrap`.
10
+
5
11
  ## 0.25.18 (2026-11-14)
6
12
 
7
13
  ### InputSteppers
package/dist/index.js CHANGED
@@ -2599,7 +2599,11 @@ const lw = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
2599
2599
  onClick: {}
2600
2600
  },
2601
2601
  setup(e) {
2602
- const n = e, t = ya(() => n.disabled), { pending: a, onClick: o } = Fv(() => n.onClick), i = h(() => n.loading || a.value), l = { sm: "h-[var(--ui-button-sm,var(--ui-control-sm))] px-2", md: "h-[var(--ui-button-md,var(--ui-control-md))] px-3", lg: "h-[var(--ui-button-lg,var(--ui-control-lg))] px-4" }, s = I(null), u = I(null), c = I(!1), f = I(!1), p = I(!1), v = (b) => b instanceof Element && (b.localName === "svg" || b.hasAttribute("data-icon"));
2602
+ const n = e, t = ya(() => n.disabled), { pending: a, onClick: o } = Fv(() => n.onClick), i = h(() => n.loading || a.value), l = {
2603
+ sm: "min-h-[var(--ui-button-sm,var(--ui-control-sm))] py-[max(0px,calc((var(--ui-button-sm,var(--ui-control-sm))_-_2px_-_1lh)_/_2))] px-2",
2604
+ md: "min-h-[var(--ui-button-md,var(--ui-control-md))] py-[max(0px,calc((var(--ui-button-md,var(--ui-control-md))_-_2px_-_1lh)_/_2))] px-3",
2605
+ lg: "min-h-[var(--ui-button-lg,var(--ui-control-lg))] py-[max(0px,calc((var(--ui-button-lg,var(--ui-control-lg))_-_2px_-_1lh)_/_2))] px-4"
2606
+ }, s = I(null), u = I(null), c = I(!1), f = I(!1), p = I(!1), v = (b) => b instanceof Element && (b.localName === "svg" || b.hasAttribute("data-icon"));
2603
2607
  function m() {
2604
2608
  const b = s.value, k = b ? [...b.childNodes].filter((K) => K.nodeType === Node.ELEMENT_NODE || K.nodeType === Node.TEXT_NODE && K.textContent?.trim()) : [], C = !!b?.textContent?.trim(), _ = !!b && !C && k.some(v), A = C && k.length > 1 && v(k[0]), V = C && k.length > 1 && v(k[k.length - 1]);
2605
2609
  _ !== c.value && (c.value = _), A !== f.value && (f.value = A), V !== p.value && (p.value = V);
@@ -2607,7 +2611,7 @@ const lw = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
2607
2611
  Re(m), Xo(m);
2608
2612
  const g = h(() => n.variant === "primary" || n.variant === "danger"), w = rw(() => n.kind), x = h(
2609
2613
  () => tt(
2610
- "relative inline-flex max-w-full min-w-0 select-none items-center justify-center gap-2 whitespace-nowrap border text-[length:var(--ui-font-size)] font-normal outline-none transition-[background-color,border-color,color,box-shadow,opacity] duration-[var(--ui-motion-fast)] active:transition-none ease-[var(--ui-motion-ease)] disabled:pointer-events-none focus-visible:shadow-[var(--ui-shadow-focus)]",
2614
+ "relative inline-flex max-w-full shrink-0 select-none items-center justify-center gap-2 border text-[length:var(--ui-font-size)] font-normal outline-none transition-[background-color,border-color,color,box-shadow,opacity] duration-[var(--ui-motion-fast)] active:transition-none ease-[var(--ui-motion-ease)] disabled:pointer-events-none focus-visible:shadow-[var(--ui-shadow-focus)]",
2611
2615
  n.variant === "text" ? "px-1 py-0.5" : l[n.size],
2612
2616
  (w.value === "tool" || n.variant === "text") && "rounded-[var(--ui-radius-control)]",
2613
2617
  w.value === "action" && n.variant !== "text" && "rounded-[var(--ui-radius-pill)]",
@@ -2619,7 +2623,7 @@ const lw = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
2619
2623
  // primary colour's text with no frame or fill, as iOS's plain tinted button
2620
2624
  // and Material's text button draw it. A press dims it; the tap box stays 44
2621
2625
  // on touch (data-ui-hit) while it is drawn its text's size.
2622
- n.variant === "text" && "shrink-0 whitespace-nowrap border-transparent bg-transparent font-medium text-[var(--ui-primary)] [--ui-spin-color:var(--ui-primary)] hover:text-[var(--ui-primary-hover)] active:opacity-50 data-[disabled]:text-[var(--ui-text-disabled)]",
2626
+ n.variant === "text" && "border-transparent bg-transparent font-medium text-[var(--ui-primary)] [--ui-spin-color:var(--ui-primary)] hover:text-[var(--ui-primary-hover)] active:opacity-50 data-[disabled]:text-[var(--ui-text-disabled)]",
2623
2627
  n.variant === "danger" && "border-[var(--ui-danger)] bg-[var(--ui-danger)] text-[var(--ui-danger-foreground)] shadow-[var(--ui-shadow-control)] [--ui-spin-color:var(--ui-danger-foreground)] hover:border-[var(--ui-danger-hover)] hover:bg-[var(--ui-danger-hover)] active:border-[var(--ui-danger-active)] active:bg-[var(--ui-danger-active)] active:shadow-[var(--ui-shadow-control-active)] data-[disabled]:shadow-none data-[disabled]:border-[color-mix(in_srgb,var(--ui-danger)_30%,var(--ui-surface))] data-[disabled]:bg-[color-mix(in_srgb,var(--ui-danger)_12%,var(--ui-surface))] data-[disabled]:text-[color-mix(in_srgb,var(--ui-danger)_55%,var(--ui-text))]",
2624
2628
  // A destructive choice beside the main action (Replace theirs next to Save as copy): the grey control with a red edge and label.
2625
2629
  n.variant === "danger-outline" && "border-[var(--ui-danger)] bg-[var(--ui-control-bg)] text-[var(--ui-danger-text)] shadow-[var(--ui-shadow-control)] [--ui-spin-color:var(--ui-danger)] hover:border-[var(--ui-danger-hover)] hover:bg-[var(--ui-danger-soft)] active:border-[var(--ui-danger-active)] active:bg-[var(--ui-danger-soft)] active:shadow-[var(--ui-shadow-control-active)] data-[disabled]:border-[color-mix(in_srgb,var(--ui-danger)_30%,var(--ui-surface))] data-[disabled]:bg-[var(--ui-control-bg-disabled)] data-[disabled]:text-[color-mix(in_srgb,var(--ui-danger)_55%,var(--ui-text))] data-[disabled]:shadow-none"
@@ -2647,7 +2651,7 @@ const lw = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
2647
2651
  L("span", {
2648
2652
  ref_key: "labelEl",
2649
2653
  ref: s,
2650
- class: ie(["ui-button-label min-w-0 truncate", f.value && "[&>:first-child]:mr-2", p.value && "[&>:last-child]:ml-2"]),
2654
+ class: ie(["ui-button-label min-w-0 whitespace-normal text-center [overflow-wrap:break-word]", f.value && "[&>:first-child]:mr-2", p.value && "[&>:last-child]:ml-2"]),
2651
2655
  "data-icon-only": c.value || void 0,
2652
2656
  "data-lead": f.value || void 0,
2653
2657
  "data-trail": p.value || void 0
@@ -28370,7 +28374,10 @@ const V2 = {
28370
28374
  }), null, 16, ["open", "items", "title", "checked-keys", "radio-values", "radio-indicator"])) : M("", !0)
28371
28375
  ], 64));
28372
28376
  }
28373
- }), yB = ["data-variant"], bB = ["disabled"], wB = { class: "min-w-0 truncate" }, xB = ["disabled", "aria-label"], Ap = "inline-flex h-[var(--ui-button-md,var(--ui-control-md))] items-center border text-[length:var(--ui-font-size)] outline-none transition-[background-color,border-color,color,box-shadow,opacity] duration-[var(--ui-motion-fast)] active:transition-none ease-[var(--ui-motion-ease)] whitespace-nowrap disabled:pointer-events-none", fG = /* @__PURE__ */ U({
28377
+ }), yB = ["data-variant"], bB = ["disabled"], wB = {
28378
+ class: "min-w-0 whitespace-normal text-center [overflow-wrap:break-word]",
28379
+ "data-split-label": ""
28380
+ }, xB = ["disabled", "aria-label"], Ap = "inline-flex min-h-[var(--ui-button-md,var(--ui-control-md))] items-center border text-[length:var(--ui-font-size)] outline-none transition-[background-color,border-color,color,box-shadow,opacity] duration-[var(--ui-motion-fast)] active:transition-none ease-[var(--ui-motion-ease)] disabled:pointer-events-none", fG = /* @__PURE__ */ U({
28374
28381
  inheritAttrs: !1,
28375
28382
  __name: "SplitButton",
28376
28383
  props: {
@@ -28383,7 +28390,7 @@ const V2 = {
28383
28390
  setup(e, { emit: n }) {
28384
28391
  const t = Jo(), a = () => Object.fromEntries(Object.entries(t).filter(([c]) => c !== "class" && c !== "style")), i = pt(e, { menuLabel: "More options" }), l = n, s = () => i.variant === "primary" ? "border-[var(--ui-primary-hover)] bg-[var(--ui-primary)] text-[var(--ui-primary-foreground)] group-hover:border-[var(--ui-primary-active)] group-hover:bg-[var(--ui-primary-hover)] group-active:border-[var(--ui-primary-active)] group-active:bg-[var(--ui-primary-active)] disabled:border-[color-mix(in_srgb,var(--ui-primary)_30%,var(--ui-surface))] disabled:bg-[color-mix(in_srgb,var(--ui-primary)_12%,var(--ui-surface))] disabled:text-[color-mix(in_srgb,var(--ui-primary)_55%,var(--ui-text))]" : "focus-visible:border-[var(--ui-primary)] disabled:border-[var(--ui-control-border)] disabled:bg-[var(--ui-control-bg-disabled)] border-[var(--ui-control-border)] bg-[var(--ui-control-bg)] text-[var(--ui-text)] group-hover:border-[var(--ui-control-border-hover)] group-hover:bg-[var(--ui-control-bg-hover)] group-active:border-[var(--ui-control-border-active)] group-active:bg-[var(--ui-control-bg-active)] disabled:text-[var(--ui-text-disabled)]", u = () => i.variant === "primary" ? i.disabled ? "bg-[color-mix(in_srgb,var(--ui-primary)_30%,var(--ui-surface))]" : "bg-[var(--ui-control-divider-on-accent)]" : i.disabled ? "opacity-50 bg-[var(--ui-control-divider)]" : "bg-[var(--ui-control-divider)]";
28385
28392
  return (c, f) => (d(), y("span", {
28386
- class: ie([r(t).class, "group inline-flex items-stretch"]),
28393
+ class: ie([r(t).class, "group inline-flex max-w-full shrink-0 items-stretch"]),
28387
28394
  style: Ee(r(t).style),
28388
28395
  "data-variant": r(i).variant,
28389
28396
  "data-syno-pkg-land-ui": ""
@@ -28393,7 +28400,7 @@ const V2 = {
28393
28400
  "data-split-main": "",
28394
28401
  "data-ui-hit": "",
28395
28402
  disabled: r(i).disabled,
28396
- class: [Ap, s(), "relative min-w-0 rounded-l-[var(--ui-radius-control)] border-r-0 px-3 focus-visible:z-10 focus-visible:shadow-[var(--ui-shadow-focus)]"],
28403
+ class: [Ap, s(), "relative min-w-0 rounded-l-[var(--ui-radius-control)] border-r-0 px-3 py-[max(0px,calc((var(--ui-button-md,var(--ui-control-md))_-_2px_-_1lh)_/_2))] focus-visible:z-10 focus-visible:shadow-[var(--ui-shadow-focus)]"],
28397
28404
  onClick: f[0] || (f[0] = (p) => l("click", p))
28398
28405
  }), [
28399
28406
  L("span", wB, [
@@ -34709,7 +34716,10 @@ const yL = ["data-ui-data-view", "data-fill", "data-ui-natural-height"], bL = {
34709
34716
  ])
34710
34717
  ], 8, Eq));
34711
34718
  }
34712
- }), qq = ["data-edge"], Fq = { class: "truncate" }, pY = /* @__PURE__ */ U({
34719
+ }), qq = ["data-edge"], Fq = {
34720
+ class: "min-w-0 whitespace-normal text-center [overflow-wrap:break-word]",
34721
+ "data-ui-new-items-pill-label": ""
34722
+ }, pY = /* @__PURE__ */ U({
34713
34723
  __name: "NewItemsPill",
34714
34724
  props: {
34715
34725
  label: {},
@@ -34721,7 +34731,7 @@ const yL = ["data-ui-data-view", "data-fill", "data-ui-natural-height"], bL = {
34721
34731
  type: "button",
34722
34732
  "data-edge": e.edge,
34723
34733
  class: ie([
34724
- "ui-new-items-pill absolute left-1/2 z-[3] inline-flex h-[var(--ui-control-md)] max-w-[calc(100%-16px)] -translate-x-1/2 items-center gap-2 rounded-[var(--ui-radius-pill)] border border-[var(--ui-primary)] bg-[var(--ui-primary)] px-3 text-[length:var(--ui-font-size)] whitespace-nowrap text-[var(--ui-primary-foreground)] shadow-[var(--ui-shadow-menu)] outline-none transition-colors duration-[var(--ui-motion-fast)] hover:bg-[var(--ui-primary-hover)] active:bg-[var(--ui-primary-active)] focus-visible:shadow-[var(--ui-shadow-focus)]",
34734
+ "ui-new-items-pill absolute left-1/2 z-[3] inline-flex min-h-[var(--ui-control-md)] w-max max-w-[calc(100%-16px)] -translate-x-1/2 items-center gap-2 rounded-[var(--ui-radius-pill)] border border-[var(--ui-primary)] bg-[var(--ui-primary)] px-3 py-[max(0px,calc((var(--ui-control-md)_-_2px_-_1lh)_/_2))] text-[length:var(--ui-font-size)] text-[var(--ui-primary-foreground)] shadow-[var(--ui-shadow-menu)] outline-none transition-colors duration-[var(--ui-motion-fast)] hover:bg-[var(--ui-primary-hover)] active:bg-[var(--ui-primary-active)] focus-visible:shadow-[var(--ui-shadow-focus)]",
34725
34735
  e.edge === "top" ? "top-2" : "bottom-2"
34726
34736
  ]),
34727
34737
  "aria-live": "polite",
@@ -14723,7 +14723,11 @@ const _T = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
14723
14723
  onClick: {}
14724
14724
  },
14725
14725
  setup(e) {
14726
- const t = e, n = ma(() => t.disabled), { pending: o, onClick: a } = Uy(() => t.onClick), r = x(() => t.loading || o.value), i = { sm: "h-[var(--ui-button-sm,var(--ui-control-sm))] px-2", md: "h-[var(--ui-button-md,var(--ui-control-md))] px-3", lg: "h-[var(--ui-button-lg,var(--ui-control-lg))] px-4" }, s = /* @__PURE__ */ L(null), l = /* @__PURE__ */ L(null), c = /* @__PURE__ */ L(!1), u = /* @__PURE__ */ L(!1), f = /* @__PURE__ */ L(!1), p = (y) => y instanceof Element && (y.localName === "svg" || y.hasAttribute("data-icon"));
14726
+ const t = e, n = ma(() => t.disabled), { pending: o, onClick: a } = Uy(() => t.onClick), r = x(() => t.loading || o.value), i = {
14727
+ sm: "min-h-[var(--ui-button-sm,var(--ui-control-sm))] py-[max(0px,calc((var(--ui-button-sm,var(--ui-control-sm))_-_2px_-_1lh)_/_2))] px-2",
14728
+ md: "min-h-[var(--ui-button-md,var(--ui-control-md))] py-[max(0px,calc((var(--ui-button-md,var(--ui-control-md))_-_2px_-_1lh)_/_2))] px-3",
14729
+ lg: "min-h-[var(--ui-button-lg,var(--ui-control-lg))] py-[max(0px,calc((var(--ui-button-lg,var(--ui-control-lg))_-_2px_-_1lh)_/_2))] px-4"
14730
+ }, s = /* @__PURE__ */ L(null), l = /* @__PURE__ */ L(null), c = /* @__PURE__ */ L(!1), u = /* @__PURE__ */ L(!1), f = /* @__PURE__ */ L(!1), p = (y) => y instanceof Element && (y.localName === "svg" || y.hasAttribute("data-icon"));
14727
14731
  function h() {
14728
14732
  const y = s.value, E = y ? [...y.childNodes].filter((T) => T.nodeType === Node.ELEMENT_NODE || T.nodeType === Node.TEXT_NODE && T.textContent?.trim()) : [], k = !!y?.textContent?.trim(), w = !!y && !k && E.some(p), _ = k && E.length > 1 && p(E[0]), O = k && E.length > 1 && p(E[E.length - 1]);
14729
14733
  w !== c.value && (c.value = w), _ !== u.value && (u.value = _), O !== f.value && (f.value = O);
@@ -14731,7 +14735,7 @@ const _T = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
14731
14735
  je(h), Ga(h);
14732
14736
  const v = x(() => t.variant === "primary" || t.variant === "danger"), m = bT(() => t.kind), b = x(
14733
14737
  () => on(
14734
- "relative inline-flex max-w-full min-w-0 select-none items-center justify-center gap-2 whitespace-nowrap border text-[length:var(--ui-font-size)] font-normal outline-none transition-[background-color,border-color,color,box-shadow,opacity] duration-[var(--ui-motion-fast)] active:transition-none ease-[var(--ui-motion-ease)] disabled:pointer-events-none focus-visible:shadow-[var(--ui-shadow-focus)]",
14738
+ "relative inline-flex max-w-full shrink-0 select-none items-center justify-center gap-2 border text-[length:var(--ui-font-size)] font-normal outline-none transition-[background-color,border-color,color,box-shadow,opacity] duration-[var(--ui-motion-fast)] active:transition-none ease-[var(--ui-motion-ease)] disabled:pointer-events-none focus-visible:shadow-[var(--ui-shadow-focus)]",
14735
14739
  t.variant === "text" ? "px-1 py-0.5" : i[t.size],
14736
14740
  (m.value === "tool" || t.variant === "text") && "rounded-[var(--ui-radius-control)]",
14737
14741
  m.value === "action" && t.variant !== "text" && "rounded-[var(--ui-radius-pill)]",
@@ -14743,7 +14747,7 @@ const _T = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
14743
14747
  // primary colour's text with no frame or fill, as iOS's plain tinted button
14744
14748
  // and Material's text button draw it. A press dims it; the tap box stays 44
14745
14749
  // on touch (data-ui-hit) while it is drawn its text's size.
14746
- t.variant === "text" && "shrink-0 whitespace-nowrap border-transparent bg-transparent font-medium text-[var(--ui-primary)] [--ui-spin-color:var(--ui-primary)] hover:text-[var(--ui-primary-hover)] active:opacity-50 data-[disabled]:text-[var(--ui-text-disabled)]",
14750
+ t.variant === "text" && "border-transparent bg-transparent font-medium text-[var(--ui-primary)] [--ui-spin-color:var(--ui-primary)] hover:text-[var(--ui-primary-hover)] active:opacity-50 data-[disabled]:text-[var(--ui-text-disabled)]",
14747
14751
  t.variant === "danger" && "border-[var(--ui-danger)] bg-[var(--ui-danger)] text-[var(--ui-danger-foreground)] shadow-[var(--ui-shadow-control)] [--ui-spin-color:var(--ui-danger-foreground)] hover:border-[var(--ui-danger-hover)] hover:bg-[var(--ui-danger-hover)] active:border-[var(--ui-danger-active)] active:bg-[var(--ui-danger-active)] active:shadow-[var(--ui-shadow-control-active)] data-[disabled]:shadow-none data-[disabled]:border-[color-mix(in_srgb,var(--ui-danger)_30%,var(--ui-surface))] data-[disabled]:bg-[color-mix(in_srgb,var(--ui-danger)_12%,var(--ui-surface))] data-[disabled]:text-[color-mix(in_srgb,var(--ui-danger)_55%,var(--ui-text))]",
14748
14752
  // A destructive choice beside the main action (Replace theirs next to Save as copy): the grey control with a red edge and label.
14749
14753
  t.variant === "danger-outline" && "border-[var(--ui-danger)] bg-[var(--ui-control-bg)] text-[var(--ui-danger-text)] shadow-[var(--ui-shadow-control)] [--ui-spin-color:var(--ui-danger)] hover:border-[var(--ui-danger-hover)] hover:bg-[var(--ui-danger-soft)] active:border-[var(--ui-danger-active)] active:bg-[var(--ui-danger-soft)] active:shadow-[var(--ui-shadow-control-active)] data-[disabled]:border-[color-mix(in_srgb,var(--ui-danger)_30%,var(--ui-surface))] data-[disabled]:bg-[var(--ui-control-bg-disabled)] data-[disabled]:text-[color-mix(in_srgb,var(--ui-danger)_55%,var(--ui-text))] data-[disabled]:shadow-none"
@@ -14771,7 +14775,7 @@ const _T = ["type", "disabled", "data-disabled", "data-loading", "data-kind", "d
14771
14775
  se("span", {
14772
14776
  ref_key: "labelEl",
14773
14777
  ref: s,
14774
- class: le(["ui-button-label min-w-0 truncate", u.value && "[&>:first-child]:mr-2", f.value && "[&>:last-child]:ml-2"]),
14778
+ class: le(["ui-button-label min-w-0 whitespace-normal text-center [overflow-wrap:break-word]", u.value && "[&>:first-child]:mr-2", f.value && "[&>:last-child]:ml-2"]),
14775
14779
  "data-icon-only": c.value || void 0,
14776
14780
  "data-lead": u.value || void 0,
14777
14781
  "data-trail": f.value || void 0
@@ -3,7 +3,7 @@
3
3
  "version": "2.11.0",
4
4
  "delivery": "bundled-patched-esm",
5
5
  "patchManifestSha256": "254a74449fede8e26aa864e795730dad7fdf41447853995f72f401cf9eba4e77",
6
- "bundleSha256": "dbeb13fb02f04d8b92cddbbfb738c1cbb7abe8ca4cd39328a7940534a3a61818",
6
+ "bundleSha256": "36ed6ae51061b6ce7bd7074f74ac406cba8cf01e91b0d8f9e7ed8f4c4b2b0a71",
7
7
  "sourceHashes": {
8
8
  "shared/useBodyScrollLock.js": "287bfb604318c4202769e4b5191896eaf0e52a952e1de898967cbe09467fcfda",
9
9
  "DismissableLayer/DismissableLayer.js": "3c8d248f0a32e01f89ca1f6202b1bb691bf5d0e4012a92535e161c35e69cdc32",