@kud/ink-ui 0.21.0 → 0.23.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/index.d.ts CHANGED
@@ -267,6 +267,28 @@ type TabItem<T extends string = string> = {
267
267
  */
268
268
  marker?: string;
269
269
  markerColor?: string;
270
+ /**
271
+ * The true size of what `count` is a window onto, drawn as `(count/total)`.
272
+ *
273
+ * A field rather than something a caller folds into `label`, for the same
274
+ * reason `marker` is one — and this one was learned the hard way. A caller
275
+ * with no channel for "there are more than these" smuggled it into the label
276
+ * as `Issues +129 (20)`, and `+` is an operator: it tells the reader to add,
277
+ * with nothing on screen to add it to. The arithmetic even works, which is
278
+ * what makes it vicious — a reader who obeys gets a real number for a question
279
+ * nobody asked, with no signal they have misread anything.
280
+ *
281
+ * A fraction is part-of-whole, the most over-learned notation there is: page 3
282
+ * of 12. Nobody computes with a slash. The distinction rides on a glyph rather
283
+ * than a hue, so it survives dimming, greyscale and colourblindness — and the
284
+ * magnitude survives with it, which is the half that matters most. `(30/37)`
285
+ * and `(20/149)` say very different things about how far a tab can be trusted,
286
+ * where a bare truncation flag says only "incomplete".
287
+ *
288
+ * Omit it when the count IS the whole, so one number keeps meaning "complete"
289
+ * and two always mean "you are looking at a sample".
290
+ */
291
+ total?: number;
270
292
  };
271
293
  type TabsProps<T extends string> = {
272
294
  active: T;
package/dist/index.js CHANGED
@@ -655,77 +655,32 @@ var ScrollView = ({
655
655
  ] });
656
656
  };
657
657
  var GAP = 2;
658
- var SLIDE_STEPS = 12;
659
- var SLIDE_MS = 28;
660
- var between = (from, to, t) => {
661
- const ease = t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
662
- const lerp = (a, b) => Math.round(a + (b - a) * ease);
663
- return {
664
- start: lerp(from.start, to.start),
665
- width: Math.max(1, lerp(from.width, to.width))
666
- };
667
- };
668
- var useSlide = (rules, active) => {
669
- const target = rules[active] ?? null;
670
- const [step, setStep] = useState(SLIDE_STEPS);
671
- const from = useRef(target);
672
- const last = useRef(active);
673
- const litIndex = useRef(active);
674
- useEffect(() => {
675
- if (last.current === active) return;
676
- const settled = step >= SLIDE_STEPS;
677
- from.current = settled ? rules[last.current] ?? target : between(
678
- from.current ?? target,
679
- rules[last.current] ?? target,
680
- step / SLIDE_STEPS
681
- );
682
- if (settled) litIndex.current = last.current;
683
- last.current = active;
684
- setStep(0);
685
- }, [active]);
686
- useEffect(() => {
687
- if (step >= SLIDE_STEPS) return;
688
- const id = setTimeout(() => setStep((s) => s + 1), SLIDE_MS);
689
- return () => clearTimeout(id);
690
- }, [step]);
691
- const arrived = step >= SLIDE_STEPS;
692
- if (arrived) litIndex.current = active;
693
- if (!target) return { rule: null, lit: litIndex.current };
694
- if (arrived || !from.current) return { rule: target, lit: active };
695
- return {
696
- rule: between(from.current, target, step / SLIDE_STEPS),
697
- lit: litIndex.current
698
- };
699
- };
700
658
  var Tabs = ({ active, items }) => {
701
659
  const cells = items.map((item) => ({
702
660
  key: item.value,
703
661
  marker: item.marker ?? "",
704
662
  markerColor: item.markerColor,
705
- text: item.count !== void 0 ? `${item.label} (${item.count})` : item.label,
663
+ text: item.count === void 0 ? item.label : item.total === void 0 ? `${item.label} (${item.count})` : `${item.label} (${item.count}/${item.total})`,
706
664
  isActive: item.value === active
707
665
  }));
708
666
  const gutterOf = (cell) => [...cell.marker].length;
709
667
  const labelOf = (cell) => [...cell.text].length;
710
- const rules = [];
711
668
  let x = 0;
669
+ let rule = { start: 0, width: 0 };
712
670
  for (const cell of cells) {
713
- rules.push({ start: x + gutterOf(cell), width: labelOf(cell) });
671
+ if (cell.isActive)
672
+ rule = { start: x + gutterOf(cell), width: labelOf(cell) };
714
673
  x += gutterOf(cell) + labelOf(cell) + GAP;
715
674
  }
716
- const activeIndex = cells.findIndex((c) => c.isActive);
717
- const slide = useSlide(rules, activeIndex);
718
- const rule = slide.rule ?? { start: 0, width: 0 };
719
- const litIndex = slide.lit;
720
675
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
721
- /* @__PURE__ */ jsx(Box, { gap: GAP, children: cells.map((cell, i) => /* @__PURE__ */ jsxs(Box, { children: [
676
+ /* @__PURE__ */ jsx(Box, { gap: GAP, children: cells.map((cell) => /* @__PURE__ */ jsxs(Box, { children: [
722
677
  cell.marker ? /* @__PURE__ */ jsx(Text, { color: cell.markerColor, children: cell.marker }) : null,
723
678
  /* @__PURE__ */ jsx(
724
679
  Text,
725
680
  {
726
- bold: i === litIndex,
727
- color: i === litIndex ? colors.accent : void 0,
728
- dimColor: i !== litIndex,
681
+ bold: cell.isActive,
682
+ color: cell.isActive ? colors.accent : void 0,
683
+ dimColor: !cell.isActive,
729
684
  children: cell.text
730
685
  }
731
686
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kud/ink-ui",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "description": "React component library for Ink CLIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",