@bitforgehq/ui 0.3.2 → 0.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/README.md +4 -4
  3. package/ai/MANIFEST.index.json +36 -0
  4. package/ai/MANIFEST.json +436 -24
  5. package/ai/REFERENCE.index.json +35 -0
  6. package/ai/REFERENCE.json +202 -10
  7. package/ai/UI_GUIDE.md +25 -4
  8. package/ai/components/app-frame.md +14 -7
  9. package/ai/components/badge.md +39 -2
  10. package/ai/components/header.md +9 -0
  11. package/ai/components/list-item.md +105 -9
  12. package/ai/components/step.md +112 -0
  13. package/ai/components/steps.md +124 -0
  14. package/ai/components/table.md +119 -5
  15. package/ai/components/timeline-event.md +144 -0
  16. package/ai/components/timeline.md +201 -0
  17. package/ai/components/toggle.md +11 -1
  18. package/ai/reference/bf-action-directive.md +3 -1
  19. package/ai/reference/bf-badge-emphasis.md +27 -0
  20. package/ai/reference/bf-labels.md +2 -0
  21. package/ai/reference/bf-select-harness.md +4 -0
  22. package/ai/reference/bf-step-heading-level.md +28 -0
  23. package/ai/reference/bf-table-align.md +1 -1
  24. package/ai/reference/bf-table-column-align.md +33 -0
  25. package/ai/reference/bf-table-column.md +7 -7
  26. package/ai/reference/bf-table-harness.md +18 -0
  27. package/ai/reference/bf-timeline-tone.md +31 -0
  28. package/ai/reference/bf-toggle-harness.md +55 -0
  29. package/ai/reference/provide-bf-labels.md +2 -2
  30. package/dark-ink.css +124 -0
  31. package/fesm2022/bitforgehq-ui-mobile.mjs +13 -3
  32. package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -1
  33. package/fesm2022/bitforgehq-ui-testing.mjs +55 -2
  34. package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
  35. package/fesm2022/bitforgehq-ui.mjs +714 -46
  36. package/fesm2022/bitforgehq-ui.mjs.map +1 -1
  37. package/llms-full.txt +1128 -26
  38. package/llms.txt +9 -0
  39. package/package.json +2 -1
  40. package/theme.css +37 -0
  41. package/types/bitforgehq-ui-testing.d.ts +90 -1
  42. package/types/bitforgehq-ui.d.ts +306 -18
@@ -8,7 +8,7 @@ Replaces built-in strings, merged over the parent's (validation merged key by ke
8
8
  out or set to `undefined` keeps the parent's string. In `ApplicationConfig.providers` it covers
9
9
  every string. In a component's `providers` it covers that sub-tree's widgets and form controls
10
10
  (`loading`, `dismiss`, `tabBar`, `tabBadge`, `back`, `refreshing`, `tableSelectAll`, `tableSortBy`,
11
- `tableSortAscending`, `tableSortDescending`, `theme`, `themeSystem`, `themeLight`, `themeDark`,
11
+ `tableSortNone`, `tableSortAscending`, `tableSortDescending`, `theme`, `themeSystem`, `themeLight`, `themeDark`,
12
12
  `breadcrumb`, `breadcrumbExpand`, `navigation`, `navBadge`, `sidebarCollapse`, `sidebarExpand`,
13
13
  `skipToContent`, `pagination`, `previousPage`, `nextPage`, `pageOf`, `goToPage`, `tabGroup`,
14
14
  `calendarPreviousMonth`, `calendarNextMonth`, `calendarChooseMonth`, `calendarChooseYear`,
@@ -17,7 +17,7 @@ every string. In a component's `providers` it covers that sub-tree's widgets and
17
17
  `dateInputUnavailable`, `timeInputHour`, `timeInputMinute`, `timeInputSecond`,
18
18
  `timeInputDayPeriod`, `timeInputOpenList`, `timeInputInvalid`, `timeInputMin`, `timeInputMax`,
19
19
  `chart`, `chartLegend`, `chartValues`, `chartShowData`, `chartHideData`, `chartCategory`,
20
- `chartValue`, `chartEmpty`, `chartError`, `validation`); the overlay services (`ok`, `cancel`,
20
+ `chartValue`, `chartEmpty`, `chartError`, `listItemUnread`, `validation`); the overlay services (`ok`, `cancel`,
21
21
  `actions`, `sheet`, `modal`, `close`, `expand`, `collapse`, `sheetPosition`, `dialog`,
22
22
  `notifications`) are root singletons and pick it up only when the caller passes its injector:
23
23
  `open(…, { injector: inject(Injector) })`.
package/dark-ink.css ADDED
@@ -0,0 +1,124 @@
1
+ /*
2
+ * @bitforgehq/ui — Ink, an opt-in dark preset: near-black surfaces one small step apart,
3
+ * see-through status tints, 1 px edges instead of heavy shadows, off-white text.
4
+ *
5
+ * Usage: import it AFTER theme.css. It redefines tokens under .dark only, so light mode is
6
+ * untouched, and it wins over theme.css's own .dark block by order:
7
+ * @import 'tailwindcss';
8
+ * @import '@bitforgehq/ui/theme.css';
9
+ * @import '@bitforgehq/ui/dark-ink.css';
10
+ *
11
+ * It sets every colour and shadow token theme.css's .dark block sets except the brand set (the
12
+ * primary family below), so the app's brand primary stays: the default dark indigo, or the
13
+ * app's own .dark brand override placed after this import. For the monochrome look of the
14
+ * mockups, paste this optional block after the import as well:
15
+ *
16
+ * .dark {
17
+ * --color-primary: #ececee;
18
+ * --color-primary-hover: #dcdce0;
19
+ * --color-primary-pressed: #cdcdd2;
20
+ * --color-primary-soft: rgb(255 255 255 / 0.08);
21
+ * --color-primary-soft-hover: rgb(255 255 255 / 0.11);
22
+ * --color-primary-soft-pressed: rgb(255 255 255 / 0.14);
23
+ * --color-primary-strong: #ffffff;
24
+ * --color-on-primary: #0b0c0e;
25
+ * --color-primary-text: #e8e9ec;
26
+ * }
27
+ *
28
+ * Every pair is contrast-checked in theme.spec.ts, alpha tints composited over the surface they
29
+ * sit on (bg, surface, surface-muted and surface-sunken), with the default dark brand and with
30
+ * the monochrome block.
31
+ */
32
+
33
+ /* Tailwind inlines a shadow token's value into the shadow-* utilities when it compiles them, so
34
+ redefining --shadow-* under .dark alone changes nothing that the utilities draw. These read
35
+ the dark value through --bf-shadow-*, which only .dark below sets; in light mode the fallback
36
+ is theme.css's own light value, so light mode compiles to the same shadows. */
37
+ @theme {
38
+ --shadow-raised: var(
39
+ --bf-shadow-raised,
40
+ 0 1px 2px rgb(31 42 34 / 0.06),
41
+ 0 8px 24px rgb(31 42 34 / 0.08)
42
+ );
43
+ --shadow-floating: var(--bf-shadow-floating, 0 10px 30px rgb(31 42 34 / 0.18));
44
+ --shadow-segment: var(--bf-shadow-segment, 0 1px 3px rgb(31 42 34 / 0.14));
45
+ }
46
+
47
+ .dark {
48
+ /* Surfaces: the page and cards near black, one step apart. */
49
+ --color-bg: #0b0c0e;
50
+ --color-surface: #121316;
51
+ --color-surface-muted: #191a1e; /* hover */
52
+ --color-surface-sunken: #0e0f11;
53
+ --color-surface-pressed: #202126;
54
+ --color-selected: rgb(255 255 255 / 0.06);
55
+
56
+ /* Status: the colour as text, its soft tint the same colour at 12 % (a see-through tint that
57
+ sits on any surface, >= 5:1 under its text on bg, surface, surface-muted and surface-sunken). */
58
+ --color-success: #4cc38a;
59
+ --color-success-soft: rgb(76 195 138 / 0.12);
60
+ --color-warning: #e5b454;
61
+ --color-warning-soft: rgb(229 180 84 / 0.12);
62
+ --color-danger: #f2706a;
63
+ /* Opaque (the danger colour at 13 % over surface), not see-through: the danger button's hover
64
+ and pressed states write danger-soft as text on the danger fill, where a tint would vanish. */
65
+ --color-danger-soft: #2f1f21;
66
+ --color-danger-pressed: #f59994;
67
+ --color-danger-border: #c9372c;
68
+ --color-info: #5eb1ef;
69
+ --color-info-soft: rgb(94 177 239 / 0.12);
70
+ /* Strong fills (>= 3:1 on bg, surface and surface-sunken), text on them >= 4.5:1. */
71
+ --color-neutral-strong: #9a9da5;
72
+ --color-on-neutral-strong: #0b0c0e; /* 7.2:1 */
73
+ --color-success-strong: #26804f;
74
+ --color-on-success-strong: #ffffff; /* 4.9:1 */
75
+ --color-warning-strong: #d99a3c;
76
+ --color-on-warning-strong: #1a1206; /* 7.6:1 */
77
+ --color-danger-strong: #c9372c;
78
+ --color-on-danger-strong: #ffffff; /* 5.2:1 */
79
+ --color-info-strong: #2a7aa8;
80
+ --color-on-info-strong: #ffffff; /* 4.7:1 */
81
+ --color-tooltip: #e8e9ec;
82
+ --color-on-tooltip: #121316; /* 15.3:1 on tooltip */
83
+
84
+ /* Charts: the default dark series (each >= 5:1 on bg and surface here, adjacent pairs distinct
85
+ under colour vision deficiency); grid lines as faint as the border, the axis >= 3:1. */
86
+ --color-chart-1: #3e9e66;
87
+ --color-chart-2: #7479ee;
88
+ --color-chart-3: #d8692f;
89
+ --color-chart-4: #1f9cb8;
90
+ --color-chart-5: #b08a1c;
91
+ --color-chart-6: #dc5893;
92
+ --color-chart-7: #a072e6;
93
+ --color-chart-8: #7f9c2c;
94
+ --color-chart-grid: #1f2024;
95
+ --color-chart-axis: #64676e;
96
+ --color-neutral: #a9adb5;
97
+ --color-neutral-soft: rgb(255 255 255 / 0.06);
98
+
99
+ /* Lines: border-strong and control-off >= 3:1 on bg, surface, surface-muted, surface-sunken. */
100
+ --color-border: #1f2024;
101
+ --color-border-strong: #64676e;
102
+ --color-divider: #18191c;
103
+ --color-control-off: #64676e;
104
+ --color-scrim: #000000;
105
+
106
+ /* Text: off-white, never pure white; muted >= 4.5:1 on every surface and on primary-soft. */
107
+ --color-text: #e8e9ec;
108
+ --color-text-secondary: #b4b7bd;
109
+ --color-text-muted: #90949b;
110
+ --color-text-subtle: #63676f; /* icons and chevrons only (>= 3:1), never text */
111
+ --color-text-disabled: #4a4d53;
112
+ --color-text-done: #6e727a;
113
+
114
+ /* A neutral focus ring (>= 5:1 on bg and surface), so it fits any brand. */
115
+ --color-ring: #8b8f97;
116
+
117
+ /* Edges instead of shadows: a 1 px white ring inside the raised and floating shadows. */
118
+ --shadow-raised: 0 0 0 1px rgb(255 255 255 / 0.06), 0 1px 2px rgb(0 0 0 / 0.6);
119
+ --shadow-floating: 0 0 0 1px rgb(255 255 255 / 0.08), 0 16px 48px rgb(0 0 0 / 0.7);
120
+ --shadow-segment: 0 1px 3px rgb(0 0 0 / 0.5);
121
+ --bf-shadow-raised: var(--shadow-raised);
122
+ --bf-shadow-floating: var(--shadow-floating);
123
+ --bf-shadow-segment: var(--shadow-segment);
124
+ }
@@ -2959,13 +2959,22 @@ var BfHeaderComponent = class BfHeaderComponent {
2959
2959
  };
2960
2960
  measure();
2961
2961
  if (typeof ResizeObserver !== "undefined") {
2962
- const observer = new ResizeObserver(measure);
2962
+ let frame = null;
2963
+ const observer = new ResizeObserver(() => {
2964
+ frame ??= requestAnimationFrame(() => {
2965
+ frame = null;
2966
+ measure();
2967
+ });
2968
+ });
2963
2969
  observer.observe(toolbar);
2964
2970
  observer.observe(start);
2965
2971
  observer.observe(end);
2966
2972
  for (const element of [title, sizer]) if (element) observer.observe(element);
2967
2973
  if (block) observer.observe(block);
2968
- onCleanup(() => observer.disconnect());
2974
+ onCleanup(() => {
2975
+ observer.disconnect();
2976
+ if (frame !== null) cancelAnimationFrame(frame);
2977
+ });
2969
2978
  }
2970
2979
  });
2971
2980
  let destroyed = false;
@@ -5157,7 +5166,8 @@ var BfActionSheetComponent = class BfActionSheetComponent {
5157
5166
  "interactive",
5158
5167
  "chevron",
5159
5168
  "disabled",
5160
- "truncate"
5169
+ "truncate",
5170
+ "unread"
5161
5171
  ],
5162
5172
  outputs: ["clicked"]
5163
5173
  },