@ceebee/ui 1.3.2 → 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/dist/client.js CHANGED
@@ -629,6 +629,16 @@ var STICKER_VARIANTS = {
629
629
  still: { opacity: 1, x: 0, y: 0, rotate: 0, scale: 1 },
630
630
  stillExit: { opacity: 0, x: 0, y: 0, rotate: 0, scale: 1 }
631
631
  };
632
+ function stableChoice(id, salt, options) {
633
+ let hash = 2166136261;
634
+ for (const character of `${salt}:${id}`) {
635
+ hash ^= character.charCodeAt(0);
636
+ hash = Math.imul(hash, 16777619);
637
+ }
638
+ return (hash >>> 0) % options;
639
+ }
640
+ var TILTS = ["left", "right", "none"];
641
+ var EXITS = ["left", "right"];
632
642
  function StickerGroupRoot({
633
643
  items,
634
644
  onDismiss,
@@ -639,9 +649,9 @@ function StickerGroupRoot({
639
649
  }) {
640
650
  const motionSettings = useMotionSettings();
641
651
  const shouldMove = motionEnabled && motionSettings.enabled;
642
- return /* @__PURE__ */ jsx("ul", { className: cn("cb-sticker-group", className), "aria-label": label, children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: items.map((item, index) => {
643
- const tilt = index % 3 === 0 ? "left" : index % 3 === 1 ? "right" : "none";
644
- const exit = index % 2 === 0 ? "left" : "right";
652
+ return /* @__PURE__ */ jsx("ul", { className: cn("cb-sticker-group", className), "aria-label": label, children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: items.map((item) => {
653
+ const tilt = TILTS[stableChoice(item.id, "tilt", TILTS.length)];
654
+ const exit = EXITS[stableChoice(item.id, "exit", EXITS.length)];
645
655
  const itemLabel = item.ariaLabel ?? (typeof item.label === "string" ? item.label : "item");
646
656
  const dismissLabel = getDismissLabel?.(item) ?? `Remove ${itemLabel}`;
647
657
  return /* @__PURE__ */ jsx(
package/dist/styles.css CHANGED
@@ -774,6 +774,19 @@ html, body { background: var(--cb-bg); color: var(--cb-fg); }
774
774
  }
775
775
  .cb-palette__input::placeholder { color: var(--cb-fg-subtle); }
776
776
 
777
+ /* The `outline: none` above states the intent, but a consumer's global `:focus-visible` reset
778
+ matches this input at the same weight and, imported after this stylesheet, wins on order — which
779
+ draws a hard box around a deliberately borderless field. Restating it against `:focus-visible`
780
+ settles it by weight instead. Focus stays visible: the search row takes the brand colour, and the
781
+ active command is highlighted the moment the palette opens. */
782
+ .cb-palette__input:focus-visible {
783
+ outline: none;
784
+ }
785
+
786
+ .cb-palette__search:focus-within {
787
+ border-bottom-color: var(--cb-tone-brand);
788
+ }
789
+
777
790
  .cb-palette__list { overflow-y: auto; padding: var(--cb-space-2); }
778
791
  .cb-palette__group + .cb-palette__group { margin-top: var(--cb-space-2); }
779
792
  .cb-palette__group-label {
@@ -1889,3 +1902,119 @@ html, body { background: var(--cb-bg); color: var(--cb-fg); }
1889
1902
  .cb-checklist__description { font-size: var(--cb-text-xs); color: var(--cb-fg-subtle); }
1890
1903
  .cb-checklist__chevron { flex: none; color: var(--cb-fg-subtle); align-self: center; }
1891
1904
  .cb-checklist__complete { padding: var(--cb-space-2) 0; }
1905
+
1906
+ /* theme/ant-prepaint.css */
1907
+ /* Ant builds its stylesheet in JavaScript, so a server-rendered document carries Ant's class names
1908
+ and none of the rules behind them. Until hydration its controls paint with the browser's native
1909
+ appearance: a square grey button on a Ceebee surface, in both colour modes.
1910
+
1911
+ Extracting Ant's rules on the server does not fix this. Ant derives its seed from live CSS Tokens,
1912
+ which a server cannot read, so extracted rules carry Ant's default light palette and a dark reader
1913
+ gets a white control instead of a tonally correct one — measured, and worse than the native
1914
+ appearance, which at least follows `color-scheme`.
1915
+
1916
+ These declarations give Ant's primitives a token-correct first paint instead. Every selector is
1917
+ wrapped in `:where()`, which contributes no specificity, so each real Ant rule wins the instant it
1918
+ arrives and nothing here competes with the runtime that owns these components. The class names are
1919
+ the ones Ant already puts in the server-rendered markup, including its variant and size classes,
1920
+ so a first paint can respect them. */
1921
+
1922
+ :where(.ant-btn) {
1923
+ display: inline-flex;
1924
+ min-height: var(--cb-control-height-md);
1925
+ align-items: center;
1926
+ justify-content: center;
1927
+ gap: var(--cb-space-2);
1928
+ padding-inline: var(--cb-space-4);
1929
+ border: var(--cb-border-width) solid var(--cb-border-strong);
1930
+ border-radius: var(--cb-radius-sm);
1931
+ background: var(--cb-surface);
1932
+ color: var(--cb-fg);
1933
+ font-family: var(--cb-font-sans);
1934
+ font-size: var(--cb-text-sm);
1935
+ }
1936
+
1937
+ :where(.ant-btn-sm) {
1938
+ min-height: var(--cb-control-height-sm);
1939
+ padding-inline: var(--cb-space-3);
1940
+ font-size: var(--cb-text-xs);
1941
+ }
1942
+
1943
+ :where(.ant-btn-lg) {
1944
+ min-height: var(--cb-control-height-lg);
1945
+ padding-inline: var(--cb-space-5);
1946
+ font-size: var(--cb-text-md);
1947
+ }
1948
+
1949
+ :where(.ant-btn-icon-only) {
1950
+ min-width: var(--cb-control-height-md);
1951
+ padding-inline: var(--cb-space-0);
1952
+ }
1953
+
1954
+ :where(.ant-btn-block) {
1955
+ width: 100%;
1956
+ }
1957
+
1958
+ /* A text or link button carries no chrome of its own, so borrowing the surface would make one look
1959
+ like an outlined button for as long as the first paint lasts. */
1960
+ :where(.ant-btn-variant-text, .ant-btn-variant-link) {
1961
+ border-color: transparent;
1962
+ background: transparent;
1963
+ }
1964
+
1965
+ :where(.ant-btn-variant-solid) {
1966
+ border-color: transparent;
1967
+ background: var(--cb-tone-brand);
1968
+ color: var(--cb-fg-on-brand);
1969
+ }
1970
+
1971
+ :where(.ant-input, .ant-input-affix-wrapper, .ant-select .ant-select-selector) {
1972
+ display: flex;
1973
+ min-height: var(--cb-control-height-md);
1974
+ align-items: center;
1975
+ gap: var(--cb-space-2);
1976
+ padding-inline: var(--cb-space-3);
1977
+ border: var(--cb-border-width) solid var(--cb-border-strong);
1978
+ border-radius: var(--cb-radius-sm);
1979
+ background: var(--cb-surface);
1980
+ color: var(--cb-fg);
1981
+ font-family: var(--cb-font-sans);
1982
+ font-size: var(--cb-text-sm);
1983
+ }
1984
+
1985
+ /* An input inside an affix wrapper is already framed by the wrapper. */
1986
+ :where(.ant-input-affix-wrapper .ant-input) {
1987
+ min-height: auto;
1988
+ padding-inline: var(--cb-space-0);
1989
+ border: none;
1990
+ background: transparent;
1991
+ }
1992
+
1993
+ /* A pseudo-element cannot live inside `:where()` — the rule would be dropped — so it sits outside
1994
+ it and carries only its own element-level weight, which Ant's `.ant-input::placeholder` outranks. */
1995
+ :where(.ant-input)::placeholder,
1996
+ :where(.ant-select-placeholder) {
1997
+ color: var(--cb-fg-muted);
1998
+ }
1999
+
2000
+ :where(.ant-segmented) {
2001
+ display: inline-flex;
2002
+ align-items: center;
2003
+ gap: var(--cb-space-1);
2004
+ padding: var(--cb-space-1);
2005
+ border-radius: var(--cb-radius-sm);
2006
+ background: var(--cb-bg-subtle);
2007
+ font-family: var(--cb-font-sans);
2008
+ font-size: var(--cb-text-xs);
2009
+ }
2010
+
2011
+ :where(.ant-segmented-item) {
2012
+ padding-inline: var(--cb-space-3);
2013
+ border-radius: var(--cb-radius-sm);
2014
+ color: var(--cb-fg-muted);
2015
+ }
2016
+
2017
+ :where(.ant-segmented-item-selected) {
2018
+ background: var(--cb-surface);
2019
+ color: var(--cb-fg);
2020
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ceebee/ui",
3
- "version": "1.3.2",
3
+ "version": "1.4.0",
4
4
  "description": "Ceebee's design system: tokens, themed primitives, motion, and onboarding.",
5
5
  "license": "MIT",
6
6
  "repository": {