@boost33/ui 0.7.1 → 0.8.0-next.1

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 (68) hide show
  1. package/CHANGELOG.md +257 -0
  2. package/dist/buttons.module.css.js +10 -0
  3. package/dist/buttons.module.css.js.map +1 -0
  4. package/dist/components/AppShell/AppShell.d.ts +129 -17
  5. package/dist/components/AppShell/AppShell.js +78 -50
  6. package/dist/components/AppShell/AppShell.js.map +1 -1
  7. package/dist/components/AppShell/AppShell.module.css.js +22 -14
  8. package/dist/components/AppShell/AppShell.module.css.js.map +1 -1
  9. package/dist/components/AppSwitcher/AppSwitcher.d.ts +92 -45
  10. package/dist/components/AppSwitcher/AppSwitcher.js +76 -68
  11. package/dist/components/AppSwitcher/AppSwitcher.js.map +1 -1
  12. package/dist/components/AppSwitcher/AppSwitcher.module.css.js +42 -36
  13. package/dist/components/AppSwitcher/AppSwitcher.module.css.js.map +1 -1
  14. package/dist/components/AppSwitcher/icons.js +10 -10
  15. package/dist/components/AppSwitcher/icons.js.map +1 -1
  16. package/dist/components/AppSwitcher/labels.d.ts +15 -23
  17. package/dist/components/AppSwitcher/labels.js +3 -4
  18. package/dist/components/AppSwitcher/labels.js.map +1 -1
  19. package/dist/components/CommandPalette/CommandPalette.d.ts +8 -2
  20. package/dist/components/CommandPalette/CommandPalette.js.map +1 -1
  21. package/dist/components/NavItem/NavItem.d.ts +15 -2
  22. package/dist/components/NavItem/NavItem.js +14 -11
  23. package/dist/components/NavItem/NavItem.js.map +1 -1
  24. package/dist/components/NavItem/NavItem.module.css.js +6 -2
  25. package/dist/components/NavItem/NavItem.module.css.js.map +1 -1
  26. package/dist/components/NavSection/NavSection.module.css.js +5 -5
  27. package/dist/components/NotificationButton/NotificationButton.d.ts +29 -0
  28. package/dist/components/NotificationButton/NotificationButton.js +23 -0
  29. package/dist/components/NotificationButton/NotificationButton.js.map +1 -0
  30. package/dist/components/NotificationButton/NotificationButton.module.css.js +14 -0
  31. package/dist/components/NotificationButton/NotificationButton.module.css.js.map +1 -0
  32. package/dist/components/NotificationButton/labels.d.ts +12 -0
  33. package/dist/components/NotificationButton/labels.js +15 -0
  34. package/dist/components/NotificationButton/labels.js.map +1 -0
  35. package/dist/components/NotificationCenter/NotificationCenter.js +37 -36
  36. package/dist/components/NotificationCenter/NotificationCenter.js.map +1 -1
  37. package/dist/components/NotificationCenter/NotificationCenter.module.css.js +43 -43
  38. package/dist/components/Sidebar/NavHeightBudgetWarning.js +10 -10
  39. package/dist/components/Sidebar/NavHeightBudgetWarning.js.map +1 -1
  40. package/dist/components/Sidebar/Sidebar.module.css.js +1 -1
  41. package/dist/components/TopBar/TopBar.d.ts +55 -4
  42. package/dist/components/TopBar/TopBar.js +24 -7
  43. package/dist/components/TopBar/TopBar.js.map +1 -1
  44. package/dist/components/TopBar/TopBar.module.css.js +12 -8
  45. package/dist/components/TopBar/TopBar.module.css.js.map +1 -1
  46. package/dist/components/TopBar/labels.d.ts +20 -0
  47. package/dist/components/TopBar/labels.js +15 -0
  48. package/dist/components/TopBar/labels.js.map +1 -0
  49. package/dist/components/WalletChip/WalletChip.d.ts +77 -2
  50. package/dist/components/WalletChip/WalletChip.js +142 -50
  51. package/dist/components/WalletChip/WalletChip.js.map +1 -1
  52. package/dist/components/WalletChip/WalletChip.module.css.js +93 -47
  53. package/dist/components/WalletChip/WalletChip.module.css.js.map +1 -1
  54. package/dist/components/WalletChip/labels.d.ts +63 -1
  55. package/dist/components/WalletChip/labels.js +21 -6
  56. package/dist/components/WalletChip/labels.js.map +1 -1
  57. package/dist/deprecated-prop-warning.d.ts +5 -0
  58. package/dist/deprecated-prop-warning.js +11 -0
  59. package/dist/deprecated-prop-warning.js.map +1 -0
  60. package/dist/index.d.ts +9 -3
  61. package/dist/index.js +55 -49
  62. package/dist/index.js.map +1 -1
  63. package/dist/nav-height-budget.d.ts +12 -9
  64. package/dist/nav-height-budget.js +3 -3
  65. package/dist/nav-height-budget.js.map +1 -1
  66. package/dist/style.css +1 -1
  67. package/dist/theme.css +1 -1
  68. package/package.json +1 -1
@@ -1,12 +1,29 @@
1
- import { jsxs as i, jsx as e } from "react/jsx-runtime";
2
- import r from "./TopBar.module.css.js";
3
- function m({ breadcrumb: a, actions: s }) {
4
- return /* @__PURE__ */ i("div", { className: r.bar, children: [
5
- /* @__PURE__ */ e("div", { className: r.breadcrumb, children: a }),
6
- s != null && /* @__PURE__ */ e("div", { className: r.actions, children: s })
1
+ import { jsxs as r, Fragment as c, jsx as n } from "react/jsx-runtime";
2
+ import { warnDeprecatedProp as u } from "../../deprecated-prop-warning.js";
3
+ import { resolveTopBarLabels as h } from "./labels.js";
4
+ import l from "./TopBar.module.css.js";
5
+ function T({ sidebarToggle: o, start: i, switcher: e, tokens: a, actions: d, labels: t, breadcrumb: m }) {
6
+ m != null && u("TopBar.breadcrumb");
7
+ const s = h(t), p = e != null || a != null;
8
+ return /* @__PURE__ */ r("div", { className: l.bar, children: [
9
+ /* @__PURE__ */ r("div", { className: l.start, children: [
10
+ o,
11
+ i
12
+ ] }),
13
+ p && /* @__PURE__ */ r("div", { className: l.centre, children: [
14
+ e != null && /* @__PURE__ */ r(c, { children: [
15
+ /* @__PURE__ */ n("span", { className: l.label, children: s.switchTools }),
16
+ e
17
+ ] }),
18
+ a != null && /* @__PURE__ */ r(c, { children: [
19
+ /* @__PURE__ */ n("span", { className: l.label, "data-after-switcher": e != null ? "true" : void 0, children: s.checkTokens }),
20
+ a
21
+ ] })
22
+ ] }),
23
+ /* @__PURE__ */ n("div", { className: l.end, children: d })
7
24
  ] });
8
25
  }
9
26
  export {
10
- m as TopBar
27
+ T as TopBar
11
28
  };
12
29
  //# sourceMappingURL=TopBar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TopBar.js","sources":["../../../src/components/TopBar/TopBar.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport styles from './TopBar.module.css'\n\nexport interface TopBarProps {\n /** The breadcrumb naming the current location, on the left of the bar. */\n breadcrumb: ReactNode\n /** Shell actions on the right -- search, notifications, the account. Omit to leave the right empty. */\n actions?: ReactNode\n}\n\nexport function TopBar({ breadcrumb, actions }: TopBarProps) {\n return (\n <div className={styles.bar}>\n <div className={styles.breadcrumb}>{breadcrumb}</div>\n {actions != null && <div className={styles.actions}>{actions}</div>}\n </div>\n )\n}\n"],"names":["TopBar","breadcrumb","actions","jsxs","styles","jsx"],"mappings":";;AAUO,SAASA,EAAO,EAAE,YAAAC,GAAY,SAAAC,KAAwB;AAC3D,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAWC,EAAO,KACrB,UAAA;AAAA,IAAA,gBAAAC,EAAC,OAAA,EAAI,WAAWD,EAAO,YAAa,UAAAH,GAAW;AAAA,IAC9CC,KAAW,QAAQ,gBAAAG,EAAC,SAAI,WAAWD,EAAO,SAAU,UAAAF,EAAA,CAAQ;AAAA,EAAA,GAC/D;AAEJ;"}
1
+ {"version":3,"file":"TopBar.js","sources":["../../../src/components/TopBar/TopBar.tsx"],"sourcesContent":["import type { ReactNode } from 'react'\nimport { warnDeprecatedProp } from '../../deprecated-prop-warning'\nimport { resolveTopBarLabels, type TopBarLabels } from './labels'\nimport styles from './TopBar.module.css'\n\nexport interface TopBarProps {\n /**\n * The control that collapses the sidebar to its 56px rail and back, at the\n * far left of the bar, before the mark (B33-1712). A slot: the product's own\n * button, which owns the collapsed state.\n *\n * It has a slot of its own because the bar stopped drawing `breadcrumb` in\n * 0.8.0, and a consumer that kept its toggle inside the breadcrumb -- the\n * Wallet did -- would otherwise lose its only way into and out of the rail on\n * upgrade, silently: the pixel diff passed the bar at 0.19% with the toggle\n * gone. No board draws it; the rail keeps working with no new design.\n */\n sidebarToggle?: ReactNode\n /**\n * The left of the bar: the Boost33 mark and the organisation's pill, as the 3\n * Nov 2026 redesign draws it (B33-1712, board 20). A slot. Inside `AppShell`\n * the shell fills it from its own `mark`, `hubHref` and `org` props, so a\n * consumer of the shell does not set this.\n */\n start?: ReactNode\n /**\n * The app switcher, at the centre of the bar after its \"Switch Tools →\"\n * label. A slot: pass `AppSwitcher`. Omit it and neither it nor its label is\n * drawn. Inside `AppShell`, the shell's `switcher` prop lands here.\n */\n switcher?: ReactNode\n /**\n * The token chip, after the switcher and its \"Check Your Tokens →\" label. A\n * slot: pass `WalletChip` with `placement=\"topbar\"`. Omit it and neither it\n * nor its label is drawn. Inside `AppShell`, the shell's `wallet` prop lands\n * here.\n */\n tokens?: ReactNode\n /**\n * The right of the bar: the notification button and the account avatar\n * (board 20). A slot -- the product's own, or the package's\n * `NotificationButton` beside the consumer's avatar.\n *\n * Search is not here and nothing replaces it: Jamal removed it on 3 Nov 2026\n * until the feature is built (B33-1710), and the CommandPalette that would\n * open from it is left out of 0.8.0 with no trigger and no shortcut.\n */\n actions?: ReactNode\n /** The centre group's two labels. Each field defaults to English. */\n labels?: Partial<TopBarLabels>\n /**\n * Was the breadcrumb on the left of the bar. **Not drawn since 0.8.0**: the\n * redesign puts the mark and the organisation there, and the page's own\n * `PageHeader` names where you are. Optional so an existing call site still\n * compiles.\n *\n * @deprecated Rendered nowhere since 0.8.0 (B33-1712). Stop passing it; in\n * development, passing it logs a console warning once.\n */\n breadcrumb?: ReactNode\n}\n\n// The bar across the top of every screen (B33-1712). Three regions: the mark\n// and organisation on the left, the switcher and token chip in a centred group,\n// and the product's actions on the right. Left and right take equal shares of\n// what the centre leaves, which is what holds the centre group in the middle of\n// the bar whatever either side holds.\n//\n// A Server Component: no state, no handlers. The two controls in the centre are\n// client components passed in as slots.\nexport function TopBar({ sidebarToggle, start, switcher, tokens, actions, labels, breadcrumb }: TopBarProps) {\n if (breadcrumb != null) warnDeprecatedProp('TopBar.breadcrumb')\n const t = resolveTopBarLabels(labels)\n const hasCentre = switcher != null || tokens != null\n\n return (\n <div className={styles.bar}>\n <div className={styles.start}>\n {sidebarToggle}\n {start}\n </div>\n {hasCentre && (\n <div className={styles.centre}>\n {switcher != null && (\n <>\n <span className={styles.label}>{t.switchTools}</span>\n {switcher}\n </>\n )}\n {tokens != null && (\n <>\n {/* The second label keeps 32px clear of the switcher, so each\n label reads as belonging to the control after it, not the one\n before it (board 20). With no switcher there is nothing to\n keep clear of, and the padding goes. */}\n <span className={styles.label} data-after-switcher={switcher != null ? 'true' : undefined}>\n {t.checkTokens}\n </span>\n {tokens}\n </>\n )}\n </div>\n )}\n <div className={styles.end}>{actions}</div>\n </div>\n )\n}\n"],"names":["TopBar","sidebarToggle","start","switcher","tokens","actions","labels","breadcrumb","warnDeprecatedProp","t","resolveTopBarLabels","hasCentre","jsxs","styles","Fragment","jsx"],"mappings":";;;;AAsEO,SAASA,EAAO,EAAE,eAAAC,GAAe,OAAAC,GAAO,UAAAC,GAAU,QAAAC,GAAQ,SAAAC,GAAS,QAAAC,GAAQ,YAAAC,KAA2B;AAC3G,EAAIA,KAAc,QAAMC,EAAmB,mBAAmB;AAC9D,QAAMC,IAAIC,EAAoBJ,CAAM,GAC9BK,IAAYR,KAAY,QAAQC,KAAU;AAEhD,SACE,gBAAAQ,EAAC,OAAA,EAAI,WAAWC,EAAO,KACrB,UAAA;AAAA,IAAA,gBAAAD,EAAC,OAAA,EAAI,WAAWC,EAAO,OACpB,UAAA;AAAA,MAAAZ;AAAA,MACAC;AAAA,IAAA,GACH;AAAA,IACCS,KACC,gBAAAC,EAAC,OAAA,EAAI,WAAWC,EAAO,QACpB,UAAA;AAAA,MAAAV,KAAY,QACX,gBAAAS,EAAAE,GAAA,EACE,UAAA;AAAA,QAAA,gBAAAC,EAAC,QAAA,EAAK,WAAWF,EAAO,OAAQ,YAAE,aAAY;AAAA,QAC7CV;AAAA,MAAA,GACH;AAAA,MAEDC,KAAU,QACT,gBAAAQ,EAAAE,GAAA,EAKE,UAAA;AAAA,QAAA,gBAAAC,EAAC,QAAA,EAAK,WAAWF,EAAO,OAAO,uBAAqBV,KAAY,OAAO,SAAS,QAC7E,UAAAM,EAAE,YAAA,CACL;AAAA,QACCL;AAAA,MAAA,EAAA,CACH;AAAA,IAAA,GAEJ;AAAA,IAEF,gBAAAW,EAAC,OAAA,EAAI,WAAWF,EAAO,KAAM,UAAAR,EAAA,CAAQ;AAAA,EAAA,GACvC;AAEJ;"}
@@ -1,12 +1,16 @@
1
- const b = "_bar_194bx_7", a = "_breadcrumb_194bx_20", c = "_actions_194bx_33", r = {
2
- bar: b,
3
- breadcrumb: a,
4
- actions: c
1
+ const t = "_bar_1lxv8_9", e = "_start_1lxv8_25", _ = "_end_1lxv8_26", l = "_centre_1lxv8_45", n = "_label_1lxv8_54", s = {
2
+ bar: t,
3
+ start: e,
4
+ end: _,
5
+ centre: l,
6
+ label: n
5
7
  };
6
8
  export {
7
- c as actions,
8
- b as bar,
9
- a as breadcrumb,
10
- r as default
9
+ t as bar,
10
+ l as centre,
11
+ s as default,
12
+ _ as end,
13
+ n as label,
14
+ e as start
11
15
  };
12
16
  //# sourceMappingURL=TopBar.module.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TopBar.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
1
+ {"version":3,"file":"TopBar.module.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -0,0 +1,20 @@
1
+ /** Every user-facing string the top bar renders itself. */
2
+ export interface TopBarLabels {
3
+ /**
4
+ * The text before the app switcher in the centre group (B33-1712, boards 18,
5
+ * 20 and 22 of the 3 Nov 2026 redesign). Text, not a control: it says what the
6
+ * control beside it is for. The arrow is part of the string, so a consumer
7
+ * writing right-to-left can turn it. Default "Switch Tools →".
8
+ */
9
+ switchTools: string;
10
+ /** The text before the token chip, on the same terms. Default "Check Your Tokens →". */
11
+ checkTokens: string;
12
+ }
13
+ export declare const defaultTopBarLabels: TopBarLabels;
14
+ /**
15
+ * Merge a consumer's partial `labels` onto the English defaults, treating an
16
+ * explicitly-`undefined` field as unsupplied, so a missed translation key falls
17
+ * back to English rather than blanking the label -- the same resolution
18
+ * `resolveAppSwitcherLabels` performs (B33-873).
19
+ */
20
+ export declare function resolveTopBarLabels(labels?: Partial<TopBarLabels>): TopBarLabels;
@@ -0,0 +1,15 @@
1
+ const t = {
2
+ switchTools: "Switch Tools →",
3
+ checkTokens: "Check Your Tokens →"
4
+ };
5
+ function r(e) {
6
+ const o = Object.fromEntries(
7
+ Object.entries(e ?? {}).filter(([, s]) => s !== void 0)
8
+ );
9
+ return { ...t, ...o };
10
+ }
11
+ export {
12
+ t as defaultTopBarLabels,
13
+ r as resolveTopBarLabels
14
+ };
15
+ //# sourceMappingURL=labels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"labels.js","sources":["../../../src/components/TopBar/labels.ts"],"sourcesContent":["// The top bar's own user-facing words, each a prop with an English default --\n// the same pattern AppSwitcherLabels and WalletChipLabels follow, for the same\n// reason: the first consumers are French-default, and the package renders what\n// it is given rather than taking an i18n dependency (B33-849).\n\n/** Every user-facing string the top bar renders itself. */\nexport interface TopBarLabels {\n /**\n * The text before the app switcher in the centre group (B33-1712, boards 18,\n * 20 and 22 of the 3 Nov 2026 redesign). Text, not a control: it says what the\n * control beside it is for. The arrow is part of the string, so a consumer\n * writing right-to-left can turn it. Default \"Switch Tools →\".\n */\n switchTools: string\n /** The text before the token chip, on the same terms. Default \"Check Your Tokens →\". */\n checkTokens: string\n}\n\nexport const defaultTopBarLabels: TopBarLabels = {\n switchTools: 'Switch Tools →',\n checkTokens: 'Check Your Tokens →',\n}\n\n/**\n * Merge a consumer's partial `labels` onto the English defaults, treating an\n * explicitly-`undefined` field as unsupplied, so a missed translation key falls\n * back to English rather than blanking the label -- the same resolution\n * `resolveAppSwitcherLabels` performs (B33-873).\n */\nexport function resolveTopBarLabels(labels?: Partial<TopBarLabels>): TopBarLabels {\n const supplied = Object.fromEntries(\n Object.entries(labels ?? {}).filter(([, value]) => value !== undefined),\n ) as Partial<TopBarLabels>\n return { ...defaultTopBarLabels, ...supplied }\n}\n"],"names":["defaultTopBarLabels","resolveTopBarLabels","labels","supplied","value"],"mappings":"AAkBO,MAAMA,IAAoC;AAAA,EAC/C,aAAa;AAAA,EACb,aAAa;AACf;AAQO,SAASC,EAAoBC,GAA8C;AAChF,QAAMC,IAAW,OAAO;AAAA,IACtB,OAAO,QAAQD,KAAU,EAAE,EAAE,OAAO,CAAC,CAAA,EAAGE,CAAK,MAAMA,MAAU,MAAS;AAAA,EAAA;AAExE,SAAO,EAAE,GAAGJ,GAAqB,GAAGG,EAAA;AACtC;"}
@@ -1,3 +1,4 @@
1
+ import { ElementType } from 'react';
1
2
  import { WalletChipLabels } from './labels';
2
3
  /**
3
4
  * The props that say nothing about a balance, so both states take them
@@ -5,6 +6,31 @@ import { WalletChipLabels } from './labels';
5
6
  * number formats it renders with.
6
7
  */
7
8
  interface WalletChipChromeProps {
9
+ /**
10
+ * Where the chip is drawn. `'sidebar'`, the default, is the card it has always
11
+ * been, pinned at the sidebar's foot. `'topbar'` is the 3 Nov 2026 redesign's
12
+ * token chip (B33-1712, boards 20 and 21): a 32px pill in the top bar, drawn
13
+ * like the app switcher, that opens a popover with the breakdown.
14
+ *
15
+ * One component in two placements rather than a second component, because the
16
+ * figures, the bar's rules and every word are the same chip's (CLAUDE.md:
17
+ * build once, add a prop). `collapsed` applies to the sidebar placement only;
18
+ * the top bar has no rail.
19
+ */
20
+ placement?: 'sidebar' | 'topbar';
21
+ /**
22
+ * Where the popover's "Open" link goes -- the Wallet. `placement="topbar"`
23
+ * only. Omit it and the popover draws no link. The consumer supplies the URL;
24
+ * Identity owns where the Wallet lives.
25
+ */
26
+ walletHref?: string;
27
+ /**
28
+ * The element the popover's "Open" link renders through, so it routes
29
+ * client-side with the locale prefix intact (ADR-0011). Defaults to `a`.
30
+ */
31
+ linkComponent?: ElementType;
32
+ /** Render the top-bar popover open on first paint -- the specimen's open state. */
33
+ defaultOpen?: boolean;
8
34
  /** The 56px rail. Abbreviates the balance and turns the split on its side. */
9
35
  collapsed?: boolean;
10
36
  /**
@@ -76,6 +102,8 @@ export interface WalletChipKnownProps extends WalletChipChromeProps {
76
102
  * required here and forbidden in {@link WalletChipUnknownProps}.
77
103
  */
78
104
  unknown?: false;
105
+ /** Absent or `false`: see {@link WalletChipTotalOnlyProps}. */
106
+ totalOnly?: false;
79
107
  /** Remaining granted tokens. Granted burns first and expires. */
80
108
  granted: number;
81
109
  /** Remaining purchased tokens. Purchased never expires. */
@@ -156,6 +184,8 @@ export interface WalletChipKnownProps extends WalletChipChromeProps {
156
184
  export interface WalletChipUnknownProps extends WalletChipChromeProps {
157
185
  /** The balance could not be confirmed. Renders as unknown, never as zero. */
158
186
  unknown: true;
187
+ totalOnly?: false;
188
+ balance?: never;
159
189
  granted?: never;
160
190
  purchased?: never;
161
191
  grantCycle?: never;
@@ -178,6 +208,51 @@ export interface WalletChipUnknownProps extends WalletChipChromeProps {
178
208
  * the members instead -- `Omit<WalletChipKnownProps, 'onTopUp'> |
179
209
  * Omit<WalletChipUnknownProps, 'onTopUp'>` -- which is why both are exported.
180
210
  */
181
- export type WalletChipProps = WalletChipKnownProps | WalletChipUnknownProps;
182
- export declare function WalletChip({ granted, purchased, grantCycle, burnedFraction, grantExpires, burnNote, unknown, collapsed, onTopUp, labels, locale }: WalletChipProps): import("react").JSX.Element;
211
+ export type WalletChipProps = WalletChipKnownProps | WalletChipUnknownProps | WalletChipTotalOnlyProps;
212
+ /**
213
+ * The top-bar chip with a real total and no drawable split (B33-1712). Debits
214
+ * draw the grant first, then purchased, and may run a set share past zero (the
215
+ * Ledger's overdraft); credits add only to the bucket they name and never pay a
216
+ * negative one off. So the Ledger can report a bucket below zero -- granted 0 /
217
+ * purchased -40 (overdrawn, total -40), or granted 1000 / purchased -40 after
218
+ * the month's grant lands (total 960, for the rest of the month). A two-segment
219
+ * bar cannot draw a negative, and clamping it to zero would draw a split nobody
220
+ * has: a split invented by the interface. So this state takes **the total and
221
+ * no split**, and draws no bar and no granted / purchased legend.
222
+ *
223
+ * Below zero the figure is the distance past zero, positive, in --color-danger,
224
+ * with the words "past zero" where a minus sign would be -- the Wallet's own
225
+ * past-zero screen (boostledger, Paper 201 screen 03), followed rather than
226
+ * inventing a third look. Nothing is broken and the copy does not say it is;
227
+ * what happens next is the consumer's `burnNote`, because the overdraft limit is
228
+ * the Ledger's. At zero or above it is the plain balance.
229
+ *
230
+ * **Top bar only.** The sidebar card has no drawing for this and the redesigned
231
+ * shell does not render it, so the type requires `placement="topbar"` rather
232
+ * than leaving the card to guess. No board draws either form: they are new
233
+ * undrawn states for the person at the gate to judge.
234
+ */
235
+ export interface WalletChipTotalOnlyProps extends WalletChipChromeProps {
236
+ placement: 'topbar';
237
+ totalOnly: true;
238
+ unknown?: false;
239
+ /**
240
+ * The balance, signed, in whole tokens: `granted + purchased` from the
241
+ * Ledger's signed figures, which its single balance row guarantees is the
242
+ * balance.
243
+ */
244
+ balance: number;
245
+ /**
246
+ * What happens next, preformatted, e.g. "Work carries on for another 930
247
+ * tokens, then paid actions stop." The consumer's, because the overdraft limit
248
+ * is the Ledger's, not the chip's.
249
+ */
250
+ burnNote?: string;
251
+ granted?: never;
252
+ purchased?: never;
253
+ grantCycle?: never;
254
+ burnedFraction?: never;
255
+ grantExpires?: never;
256
+ }
257
+ export declare function WalletChip(props: WalletChipProps): import("react").JSX.Element;
183
258
  export {};
@@ -1,71 +1,163 @@
1
1
  "use client";
2
- import { jsxs as l, jsx as e } from "react/jsx-runtime";
3
- import a from "./WalletChip.module.css.js";
4
- import { thousandsFigure as A, formatTokens as m, DEFAULT_WALLET_LOCALE as M } from "./format.js";
5
- import { WalletMark as R, RetryMark as W } from "./icons.js";
6
- import { resolveWalletChipLabels as w } from "./labels.js";
7
- const y = 0.8, F = "var(--spacing-wallet-segment-min)";
8
- function g(s, r) {
9
- const t = r > 0 ? s / r * 100 : 0;
10
- return s <= 0 ? `${t}%` : `max(${t}%, ${F})`;
2
+ import { jsx as a, jsxs as n, Fragment as P } from "react/jsx-runtime";
3
+ import { useAnchoredOverlay as U } from "../../anchored-overlay.js";
4
+ import { Chevron as $ } from "../AppSwitcher/icons.js";
5
+ import y from "../../buttons.module.css.js";
6
+ import e from "./WalletChip.module.css.js";
7
+ import { formatTokens as o, DEFAULT_WALLET_LOCALE as k, thousandsFigure as w } from "./format.js";
8
+ import { WalletMark as x, RetryMark as O } from "./icons.js";
9
+ import { resolveWalletChipLabels as A } from "./labels.js";
10
+ const E = 0.8, G = "var(--spacing-wallet-segment-min)";
11
+ function L(i, l) {
12
+ const t = l > 0 ? i / l * 100 : 0;
13
+ return i <= 0 ? `${t}%` : `max(${t}%, ${G})`;
11
14
  }
12
- function B({ granted: s, purchased: r, cycleTotal: t, tone: h, label: o }) {
13
- return /* @__PURE__ */ l("div", { className: a.bar, "data-tone": h, role: "img", "aria-label": o, children: [
14
- /* @__PURE__ */ e("span", { className: a.segmentGranted, "data-testid": "segment-granted", style: { width: g(s, t) } }),
15
- /* @__PURE__ */ e("span", { className: a.segmentPurchased, "data-testid": "segment-purchased", style: { width: g(r, t) } })
15
+ function R({ granted: i, purchased: l, cycleTotal: t, tone: p, label: r }) {
16
+ return /* @__PURE__ */ n("div", { className: e.bar, "data-tone": p, role: "img", "aria-label": r, children: [
17
+ /* @__PURE__ */ a("span", { className: e.segmentGranted, "data-testid": "segment-granted", style: { width: L(i, t) } }),
18
+ /* @__PURE__ */ a("span", { className: e.segmentPurchased, "data-testid": "segment-purchased", style: { width: L(l, t) } })
16
19
  ] });
17
20
  }
18
- function $({ granted: s = 0, purchased: r = 0, grantCycle: t, burnedFraction: h, grantExpires: o, burnNote: p, unknown: n = !1, collapsed: x = !1, onTopUp: u, labels: E, locale: d = M }) {
19
- const i = w(E), b = () => i.bar(m(s, d), m(r, d), m(s + r, d)), v = s + r, f = (t ?? s) + r, U = t !== void 0 && t > 0 ? (t - s) / t : 0, L = h ?? U, c = !n && L >= y;
20
- if (x) {
21
- const N = n ? void 0 : i.railFigure(A(v, d));
22
- return /* @__PURE__ */ l("div", { className: a.rail, role: "group", "aria-label": N === void 0 ? i.railBalanceUnknown : i.railBalance(N), tabIndex: 0, children: [
23
- /* @__PURE__ */ e(R, { className: a.railIcon }),
24
- /* @__PURE__ */ e("span", { className: a.railFigure, children: N ?? "—" }),
25
- n ? /* @__PURE__ */ e("span", { className: a.srOnly, children: i.railUnknown }) : /* @__PURE__ */ e(B, { granted: s, purchased: r, cycleTotal: f, tone: c ? "threshold" : "rest", label: b() })
21
+ function J(i) {
22
+ return i.totalOnly === !0 ? /* @__PURE__ */ a(W, { ...i }) : i.placement === "topbar" ? /* @__PURE__ */ a(M, { ...i }) : /* @__PURE__ */ a(I, { ...i });
23
+ }
24
+ function M({ granted: i = 0, purchased: l = 0, grantExpires: t, burnNote: p, unknown: r = !1, onTopUp: v, labels: m, locale: u = k, walletHref: c, linkComponent: g, defaultOpen: h }) {
25
+ const s = A(m), d = U({ defaultOpen: h }), B = g ?? "a", b = i + l, F = b, f = r ? "—" : o(b, u), N = () => s.bar(o(i, u), o(l, u), o(b, u));
26
+ return /* @__PURE__ */ n("div", { className: e.topRoot, children: [
27
+ /* @__PURE__ */ n("button", { type: "button", className: e.topTrigger, "aria-label": r ? s.railBalanceUnknown : s.railBalance(f), onClick: d.toggle, ...d.triggerProps, children: [
28
+ /* @__PURE__ */ n("span", { className: e.topFigure, "aria-hidden": "true", children: [
29
+ /* @__PURE__ */ a("span", { className: e.topAmount, children: f }),
30
+ /* @__PURE__ */ a("span", { className: e.topUnit, children: s.unit })
31
+ ] }),
32
+ !r && /* @__PURE__ */ a(T, { granted: i, purchased: l, total: F, className: e.topBar }),
33
+ /* @__PURE__ */ a($, { className: e.topChevron })
34
+ ] }),
35
+ d.open && /* @__PURE__ */ n("div", { ...d.panelProps, className: e.popover, "aria-label": s.popover, children: [
36
+ /* @__PURE__ */ n("div", { className: e.popHead, children: [
37
+ /* @__PURE__ */ n("span", { className: e.popFigure, children: [
38
+ /* @__PURE__ */ a("span", { className: e.popAmount, children: f }),
39
+ /* @__PURE__ */ a("span", { className: e.popUnit, children: s.unit })
40
+ ] }),
41
+ c !== void 0 && /* @__PURE__ */ a(B, { className: y.quiet, href: c, onClick: d.close, children: s.open })
42
+ ] }),
43
+ r ? /* @__PURE__ */ a("p", { className: e.popNote, children: s.balanceUnknown }) : /* @__PURE__ */ n(P, { children: [
44
+ /* @__PURE__ */ a(T, { granted: i, purchased: l, total: F, className: e.popBar, label: N() }),
45
+ /* @__PURE__ */ n("ul", { className: e.legend, children: [
46
+ /* @__PURE__ */ n("li", { className: e.legendRow, children: [
47
+ /* @__PURE__ */ a("span", { className: e.swatchGranted, "aria-hidden": "true" }),
48
+ /* @__PURE__ */ n("span", { className: e.legendText, children: [
49
+ /* @__PURE__ */ a("span", { className: e.legendFigure, children: s.grantedFigure(o(i, u)) }),
50
+ /* @__PURE__ */ a("span", { className: e.legendNote, children: t ? s.grantedNote(t) : s.grantedNoteUndated })
51
+ ] })
52
+ ] }),
53
+ /* @__PURE__ */ n("li", { className: e.legendRow, children: [
54
+ /* @__PURE__ */ a("span", { className: e.swatchPurchased, "aria-hidden": "true" }),
55
+ /* @__PURE__ */ n("span", { className: e.legendText, children: [
56
+ /* @__PURE__ */ a("span", { className: e.legendFigure, children: s.purchasedFigure(o(l, u)) }),
57
+ /* @__PURE__ */ a("span", { className: e.legendNote, children: s.purchasedNote })
58
+ ] })
59
+ ] })
60
+ ] }),
61
+ (p || v !== void 0) && /* @__PURE__ */ n("div", { className: e.popFoot, children: [
62
+ p && /* @__PURE__ */ a("p", { className: e.popNote, children: p }),
63
+ v !== void 0 && /* @__PURE__ */ a("button", { type: "button", className: `${y.primary} ${e.buy}`, "data-tone": "accent", onClick: v, children: s.buyTokens })
64
+ ] })
65
+ ] })
66
+ ] })
67
+ ] });
68
+ }
69
+ function W({ balance: i, burnNote: l, onTopUp: t, labels: p, locale: r = k, walletHref: v, linkComponent: m, defaultOpen: u }) {
70
+ const c = A(p), g = U({ defaultOpen: u }), h = m ?? "a", s = i < 0, d = o(s ? -i : i, r);
71
+ return /* @__PURE__ */ n("div", { className: e.topRoot, "data-past-zero": s ? "true" : void 0, children: [
72
+ /* @__PURE__ */ n("button", { type: "button", className: e.topTrigger, "aria-label": s ? c.pastZeroBalance(d) : c.railBalance(d), onClick: g.toggle, ...g.triggerProps, children: [
73
+ /* @__PURE__ */ n("span", { className: e.topFigure, "aria-hidden": "true", children: [
74
+ /* @__PURE__ */ a("span", { className: e.topAmount, children: d }),
75
+ /* @__PURE__ */ a("span", { className: e.topUnit, children: s ? c.pastZero : c.unit })
76
+ ] }),
77
+ /* @__PURE__ */ a($, { className: e.topChevron })
78
+ ] }),
79
+ g.open && /* @__PURE__ */ n("div", { ...g.panelProps, className: e.popover, "aria-label": c.popover, children: [
80
+ /* @__PURE__ */ n("div", { className: e.popHead, children: [
81
+ /* @__PURE__ */ n("span", { className: e.popFigure, children: [
82
+ /* @__PURE__ */ a("span", { className: e.popAmount, children: d }),
83
+ /* @__PURE__ */ a("span", { className: e.popUnit, children: s ? c.pastZeroLong : c.unit })
84
+ ] }),
85
+ v !== void 0 && /* @__PURE__ */ a(h, { className: y.quiet, href: v, onClick: g.close, children: c.open })
86
+ ] }),
87
+ (l || t !== void 0) && /* @__PURE__ */ n("div", { className: e.popFoot, children: [
88
+ l && /* @__PURE__ */ a("p", { className: e.popNote, children: l }),
89
+ t !== void 0 && /* @__PURE__ */ a("button", { type: "button", className: `${y.primary} ${e.buy}`, "data-tone": "accent", onClick: t, children: c.buyTokens })
90
+ ] })
91
+ ] })
92
+ ] });
93
+ }
94
+ function T({ granted: i, purchased: l, total: t, className: p, label: r }) {
95
+ return /* @__PURE__ */ n("span", { className: p, role: r ? "img" : void 0, "aria-label": r, "aria-hidden": r ? void 0 : "true", children: [
96
+ /* @__PURE__ */ a("span", { className: e.segmentGranted, "data-segment": "granted", style: { width: L(i, t) } }),
97
+ /* @__PURE__ */ a("span", { className: e.segmentPurchased, "data-segment": "purchased", style: { width: L(l, t) } })
98
+ ] });
99
+ }
100
+ function I({ granted: i = 0, purchased: l = 0, grantCycle: t, burnedFraction: p, grantExpires: r, burnNote: v, unknown: m = !1, collapsed: u = !1, onTopUp: c, labels: g, locale: h = k }) {
101
+ const s = A(g), d = () => s.bar(o(i, h), o(l, h), o(i + l, h)), B = i + l, b = (t ?? i) + l, F = t !== void 0 && t > 0 ? (t - i) / t : 0, f = p ?? F, N = !m && f >= E;
102
+ if (u) {
103
+ const C = m ? void 0 : s.railFigure(w(B, h));
104
+ return /* @__PURE__ */ n("div", { className: e.rail, role: "group", "aria-label": C === void 0 ? s.railBalanceUnknown : s.railBalance(C), tabIndex: 0, children: [
105
+ /* @__PURE__ */ a(x, { className: e.railIcon }),
106
+ /* @__PURE__ */ a("span", { className: e.railFigure, children: C ?? "—" }),
107
+ m ? /* @__PURE__ */ a("span", { className: e.srOnly, children: s.railUnknown }) : /* @__PURE__ */ a(R, { granted: i, purchased: l, cycleTotal: b, tone: N ? "threshold" : "rest", label: d() })
26
108
  ] });
27
109
  }
28
- return /* @__PURE__ */ l("div", { className: a.chip, role: "group", "aria-label": i.region, tabIndex: 0, "data-threshold": c ? "true" : void 0, "data-unknown": n ? "true" : void 0, children: [
29
- /* @__PURE__ */ l("div", { className: a.header, children: [
30
- /* @__PURE__ */ e("span", { className: a.name, children: i.name }),
31
- c && /* @__PURE__ */ l("span", { className: a.pill, children: [
32
- Math.round(L * 100),
110
+ return /* @__PURE__ */ n("div", { className: e.chip, role: "group", "aria-label": s.region, tabIndex: 0, "data-threshold": N ? "true" : void 0, "data-unknown": m ? "true" : void 0, children: [
111
+ /* @__PURE__ */ n("div", { className: e.header, children: [
112
+ /* @__PURE__ */ a("span", { className: e.name, children: s.name }),
113
+ N && /* @__PURE__ */ n("span", { className: e.pill, children: [
114
+ Math.round(f * 100),
33
115
  "%"
34
116
  ] })
35
117
  ] }),
36
- n ? /* @__PURE__ */ l("div", { className: a.figure, children: [
37
- /* @__PURE__ */ e("span", { className: a.amount, "aria-hidden": "true", children: "—" }),
38
- /* @__PURE__ */ e(W, { className: a.retry }),
39
- /* @__PURE__ */ e("span", { className: a.srOnly, children: i.balanceUnknown })
40
- ] }) : /* @__PURE__ */ l("div", { className: a.figure, children: [
41
- /* @__PURE__ */ e("span", { className: a.amount, children: m(v, d) }),
42
- /* @__PURE__ */ e("span", { className: a.unit, children: i.unit })
118
+ m ? /* @__PURE__ */ n("div", { className: e.figure, children: [
119
+ /* @__PURE__ */ a("span", { className: e.amount, "aria-hidden": "true", children: "—" }),
120
+ /* @__PURE__ */ a(O, { className: e.retry }),
121
+ /* @__PURE__ */ a("span", { className: e.srOnly, children: s.balanceUnknown })
122
+ ] }) : /* @__PURE__ */ n("div", { className: e.figure, children: [
123
+ /* @__PURE__ */ a("span", { className: e.amount, children: o(B, h) }),
124
+ /* @__PURE__ */ a("span", { className: e.unit, children: s.unit })
43
125
  ] }),
44
- n ? /* @__PURE__ */ e("div", { className: a.bar, "data-tone": "unknown", "aria-hidden": "true" }) : /* @__PURE__ */ e(B, { granted: s, purchased: r, cycleTotal: f, tone: c ? "threshold" : "rest", label: b() }),
45
- !n && !c && /* @__PURE__ */ l("div", { className: a.details, children: [
46
- /* @__PURE__ */ l("dl", { className: a.split, children: [
47
- /* @__PURE__ */ l("div", { className: a.splitRow, children: [
48
- /* @__PURE__ */ l("dt", { className: a.splitLabel, children: [
49
- /* @__PURE__ */ e("span", { className: a.dotGranted, "aria-hidden": "true" }),
50
- i.granted
126
+ m ? /* @__PURE__ */ a("div", { className: e.bar, "data-tone": "unknown", "aria-hidden": "true" }) : /* @__PURE__ */ a(R, { granted: i, purchased: l, cycleTotal: b, tone: N ? "threshold" : "rest", label: d() }),
127
+ !m && !N && /* @__PURE__ */ n("div", { className: e.details, children: [
128
+ /* @__PURE__ */ n("dl", { className: e.split, children: [
129
+ /* @__PURE__ */ n("div", { className: e.splitRow, children: [
130
+ /* @__PURE__ */ n("dt", { className: e.splitLabel, children: [
131
+ /* @__PURE__ */ a("span", { className: e.dotGranted, "aria-hidden": "true" }),
132
+ s.granted
51
133
  ] }),
52
- /* @__PURE__ */ e("dd", { className: a.splitAmount, children: m(s, d) })
134
+ /* @__PURE__ */ a("dd", { className: e.splitAmount, children: o(i, h) })
53
135
  ] }),
54
- /* @__PURE__ */ l("div", { className: a.splitRow, children: [
55
- /* @__PURE__ */ l("dt", { className: a.splitLabel, children: [
56
- /* @__PURE__ */ e("span", { className: a.dotPurchased, "aria-hidden": "true" }),
57
- i.purchased
136
+ /* @__PURE__ */ n("div", { className: e.splitRow, children: [
137
+ /* @__PURE__ */ n("dt", { className: e.splitLabel, children: [
138
+ /* @__PURE__ */ a("span", { className: e.dotPurchased, "aria-hidden": "true" }),
139
+ s.purchased
58
140
  ] }),
59
- /* @__PURE__ */ e("dd", { className: a.splitAmount, children: m(r, d) })
141
+ /* @__PURE__ */ a("dd", { className: e.splitAmount, children: o(l, h) })
60
142
  ] })
61
143
  ] }),
62
- o && /* @__PURE__ */ e("p", { className: a.footer, children: i.grantExpiry(o) })
144
+ r && /* @__PURE__ */ a("p", { className: e.footer, children: s.grantExpiry(r) })
63
145
  ] }),
64
- c && p && /* @__PURE__ */ e("p", { className: a.burnNote, children: p }),
65
- !n && u !== void 0 && /* @__PURE__ */ e("button", { type: "button", className: a.topUp, "data-grown": c ? "true" : void 0, onClick: u, children: i.topUp })
146
+ N && v && /* @__PURE__ */ a("p", { className: e.burnNote, children: v }),
147
+ !m && c !== void 0 && /* @__PURE__ */ a(
148
+ "button",
149
+ {
150
+ type: "button",
151
+ className: `${N ? y.primary : y.quiet} ${e.topUp}`,
152
+ "data-tone": N ? "accent" : void 0,
153
+ "data-grown": N ? "true" : void 0,
154
+ onClick: c,
155
+ children: s.topUp
156
+ }
157
+ )
66
158
  ] });
67
159
  }
68
160
  export {
69
- $ as WalletChip
161
+ J as WalletChip
70
162
  };
71
163
  //# sourceMappingURL=WalletChip.js.map