@boost33/ui 0.8.0-next.2 → 0.8.0-next.4

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
@@ -219,6 +219,80 @@ Repo-only: the specimen's "Shell redesign — B33-1710" route grows the top bar,
219
219
  the open token popover, board 22's nothing-purchased chip, and the unknown,
220
220
  past-zero and total-only chips.
221
221
 
222
+ ### Fixed — the top bar fits at 1024px; the token popover stays on screen (0.8.0-next.4)
223
+
224
+ - **Below 80rem of bar, the centre group's two labels leave the screen.**
225
+ next.3 stopped the regions overlapping, but the centre does not shrink, so at
226
+ 1024px Content's bar still needed 1067px and clipped the avatar. Now
227
+ "Switch Tools →" and "Check Your Tokens →" are hidden visually wherever the
228
+ bar's content box is under 80rem (1280px; a full-width bar in a window under
229
+ 1344px) and the centre gives back about 280px. They stay in the
230
+ accessibility tree, before the control each introduces, so a screen reader
231
+ hears the same thing at every width. A container query on the bar
232
+ (`container: boost33-top-bar / inline-size`), so a bar narrower than the
233
+ window is measured by its own width. Measured in Chromium at 1024px with a
234
+ 256px start group and either a 70px or a 220px actions group: no overflow and
235
+ no overlap. If you write container queries in the bar's slots, name your own
236
+ container: the bar is now a container.
237
+ - **The token popover stays on screen.** It hangs from the pill's left edge and
238
+ is 340px wide. At 390px its right edge was at 535px, cutting the threshold
239
+ line and the reset note, and at 1024px it overshot by 8px. It now slides left
240
+ by exactly its overshoot to keep 16px from the right edge (never past 16px
241
+ from the left), and is never wider than the viewport less 32px. Both the
242
+ split chip and `totalOnly` do this. It is measured before paint and again on
243
+ resize.
244
+ - **Below `chromeFrom` the shell fills the screen**: `min-height: 100dvh`
245
+ instead of next.3's `100%`, which resolved against app wrappers with no
246
+ height and left short pages ending grey (Content).
247
+ - **No approved screenshot moves**: all 40 gated states measure the same with
248
+ and without these changes, each on a fresh specimen build.
249
+
250
+ ### Fixed — the top-bar token chip warns again past 80% of the grant; the top bar holds its layout (0.8.0-next.3)
251
+
252
+ - **The 80% threshold is back in the top bar.** 0.8.0-next.0 moved the chip to
253
+ the top bar without its threshold state, so a seller who had burned 87% of the
254
+ month's grant saw the same chip as one at 10%, and nothing here said so
255
+ (found by Score). `placement="topbar"` now reads `grantCycle` and
256
+ `burnedFraction` exactly as the sidebar card does (the consumer's
257
+ `burnedFraction` wins, otherwise it is derived from `grantCycle`, and with
258
+ neither nothing is claimed). Past 80%:
259
+ - with `grantCycle`, the bar in the chip and in the popover measures against
260
+ what the cycle started with, so it shortens and the burned share shows as
261
+ the warning-tinted track: the sidebar card's drawing (Jamal, 4 Nov 2026).
262
+ With `burnedFraction` alone there is no honest denominator, so the bar
263
+ stays full;
264
+ - the popover shows a line above the runway note, and the chip's accessible
265
+ name ends with it, so the warning is never colour alone. **New label
266
+ `thresholdNote`**, a template with `%percent%`, formatted for `locale`
267
+ ("87%", "87 %"). Default `You've used %percent% of this month's grant.`
268
+ A catalogue typed as a full `WalletChipLabels` must add it; that is the
269
+ typecheck catching a missing translation;
270
+ - the root carries `data-threshold="true"`. Buy tokens is unchanged: the
271
+ accent primary.
272
+ Keep passing `grantCycle` (or `burnedFraction`) to the top-bar chip.
273
+ - **The top bar keeps its regions apart at any width.** At 1024px the start
274
+ group (mark and organisation pill) was given less than it held and painted
275
+ across "Switch Tools →" (Content, Wallet, Activity, Outbound). The bar is now
276
+ a three-column grid whose sides are never narrower than their contents: where
277
+ everything fits, the centre group sits in the middle as before; where it does
278
+ not, the centre moves off the middle instead of under the pill. Below that,
279
+ on a phone with no `chromeFrom`, the bar runs off the right edge in order
280
+ rather than piling up (Score). **No approved screenshot moves**: every gated
281
+ state measures the same pixel count with and without the change.
282
+ - **The top bar is a `<header>`**, the page's banner landmark, so assistive tech
283
+ can jump to it and a test can scope to it (Score). `getByRole('banner')`
284
+ finds it. The census in `scripts/border-proof.ts` records the bar's hairline on
285
+ a `header` now; the pixels did not move.
286
+ - **The popover's reset note ends on the date.** `grantedNote` defaults to
287
+ `Included each month · resets %date%`, without the `Resets %date%.`
288
+ full stop that printed "30 sept.." for a French date (Score). If you
289
+ translate it, keep punctuation off the end of `%date%`. `grantExpires` is one
290
+ date in both placements, the day this month's grant runs out and the next
291
+ lands. The sidebar says it as an expiry, the popover as a reset.
292
+ - **Below `chromeFrom` the shell still fills its root** (`min-height: 100%`),
293
+ so a short page keeps the white ground to the bottom of the screen (Content).
294
+ Replaced by `100dvh` in next.4.
295
+
222
296
  ### Added — `AppShell` gets out of the way on a phone: `chromeFrom` and `phoneChrome`
223
297
 
224
298
  AppShell has no phone layout, and the 0.8 top bar runs off a 390px screen.
@@ -1,28 +1,28 @@
1
- const o = "_shell_1rvaz_13", n = "_body_1rvaz_24", t = "_appName_1rvaz_39", _ = "_foot_1rvaz_65", a = "_actionSlot_1rvaz_79", c = "_action_1rvaz_79", s = "_srOnly_1rvaz_103", e = "_nav_1rvaz_116", r = "_main_1rvaz_125", l = "_content_1rvaz_146", v = "_phoneChrome_1rvaz_201", z = {
1
+ const o = "_shell_l6zer_13", n = "_body_l6zer_24", t = "_appName_l6zer_39", _ = "_foot_l6zer_65", e = "_actionSlot_l6zer_79", l = "_action_l6zer_79", c = "_srOnly_l6zer_103", s = "_nav_l6zer_116", a = "_main_l6zer_125", r = "_content_l6zer_146", z = "_phoneChrome_l6zer_207", p = {
2
2
  shell: o,
3
3
  body: n,
4
4
  appName: t,
5
5
  foot: _,
6
- actionSlot: a,
7
- action: c,
8
- srOnly: s,
9
- nav: e,
10
- main: r,
11
- content: l,
12
- phoneChrome: v
6
+ actionSlot: e,
7
+ action: l,
8
+ srOnly: c,
9
+ nav: s,
10
+ main: a,
11
+ content: r,
12
+ phoneChrome: z
13
13
  };
14
14
  export {
15
- c as action,
16
- a as actionSlot,
15
+ l as action,
16
+ e as actionSlot,
17
17
  t as appName,
18
18
  n as body,
19
- l as content,
20
- z as default,
19
+ r as content,
20
+ p as default,
21
21
  _ as foot,
22
- r as main,
23
- e as nav,
24
- v as phoneChrome,
22
+ a as main,
23
+ s as nav,
24
+ z as phoneChrome,
25
25
  o as shell,
26
- s as srOnly
26
+ c as srOnly
27
27
  };
28
28
  //# sourceMappingURL=AppShell.module.css.js.map
@@ -1,26 +1,26 @@
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: [
1
+ import { jsxs as l, Fragment as c, jsx as n } from "react/jsx-runtime";
2
+ import { warnDeprecatedProp as h } from "../../deprecated-prop-warning.js";
3
+ import { resolveTopBarLabels as u } from "./labels.js";
4
+ import e from "./TopBar.module.css.js";
5
+ function T({ sidebarToggle: o, start: d, switcher: r, tokens: a, actions: i, labels: t, breadcrumb: m }) {
6
+ m != null && h("TopBar.breadcrumb");
7
+ const s = u(t), p = r != null || a != null;
8
+ return /* @__PURE__ */ l("header", { className: e.bar, children: [
9
+ /* @__PURE__ */ l("div", { className: e.start, children: [
10
10
  o,
11
- i
11
+ d
12
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
13
+ p && /* @__PURE__ */ l("div", { className: e.centre, children: [
14
+ r != null && /* @__PURE__ */ l(c, { children: [
15
+ /* @__PURE__ */ n("span", { className: e.label, children: s.switchTools }),
16
+ r
17
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 }),
18
+ a != null && /* @__PURE__ */ l(c, { children: [
19
+ /* @__PURE__ */ n("span", { className: e.label, "data-after-switcher": r != null ? "true" : void 0, children: s.checkTokens }),
20
20
  a
21
21
  ] })
22
22
  ] }),
23
- /* @__PURE__ */ n("div", { className: l.end, children: d })
23
+ /* @__PURE__ */ n("div", { className: e.end, children: i })
24
24
  ] });
25
25
  }
26
26
  export {
@@ -1 +1 @@
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
+ {"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 // A <header>, so the bar is the page's banner landmark and a screen-reader\n // user can jump to it, and an end-to-end test can scope to it (score-main,\n // 0.8.0-next.2). Inside AppShell it is never within <main> or an <article>,\n // which is what makes a <header> a banner. `display: grid` is set on the\n // class, so the element swap changes no box.\n return (\n <header 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 </header>\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;AAOhD,SACE,gBAAAQ,EAAC,UAAA,EAAO,WAAWC,EAAO,KACxB,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,15 +1,15 @@
1
- const t = "_bar_1lxv8_9", e = "_start_1lxv8_25", _ = "_end_1lxv8_26", l = "_centre_1lxv8_45", n = "_label_1lxv8_54", s = {
1
+ const t = "_bar_1fqrh_9", e = "_start_1fqrh_40", r = "_end_1fqrh_41", _ = "_centre_1fqrh_60", n = "_label_1fqrh_69", s = {
2
2
  bar: t,
3
3
  start: e,
4
- end: _,
5
- centre: l,
4
+ end: r,
5
+ centre: _,
6
6
  label: n
7
7
  };
8
8
  export {
9
9
  t as bar,
10
- l as centre,
10
+ _ as centre,
11
11
  s as default,
12
- _ as end,
12
+ r as end,
13
13
  n as label,
14
14
  e as start
15
15
  };
@@ -155,7 +155,12 @@ export interface WalletChipKnownProps extends WalletChipChromeProps {
155
155
  * wrong figure that looks wrong is the one that gets fixed.
156
156
  */
157
157
  burnedFraction?: number;
158
- /** When the current grant expires, preformatted for display, e.g. "30 Sep". */
158
+ /**
159
+ * When the current grant expires, preformatted for display, e.g. "30 Sep":
160
+ * the day this month's grant runs out and the next one lands. The sidebar
161
+ * card says it as an expiry (`labels.grantExpiry`), the top-bar popover as a
162
+ * reset (`labels.grantedNote`); both are this one date.
163
+ */
159
164
  grantExpires?: string;
160
165
  /**
161
166
  * The threshold state's runway line, preformatted, e.g. "About four days left
@@ -1,150 +1,172 @@
1
1
  "use client";
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";
2
+ import { jsx as a, jsxs as t, Fragment as Z } from "react/jsx-runtime";
3
+ import { useRef as W, useLayoutEffect as z } from "react";
4
+ import { useAnchoredOverlay as G } from "../../anchored-overlay.js";
5
+ import { Chevron as M } from "../AppSwitcher/icons.js";
5
6
  import y from "../../buttons.module.css.js";
6
7
  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})`;
8
+ import { formatTokens as v, DEFAULT_WALLET_LOCALE as $, formatPercent as j, thousandsFigure as D } from "./format.js";
9
+ import { WalletMark as H, RetryMark as V } from "./icons.js";
10
+ import { resolveWalletChipLabels as w } from "./labels.js";
11
+ const _ = 0.8, X = "var(--spacing-wallet-segment-min)";
12
+ function P(s, i) {
13
+ const n = i > 0 ? s / i * 100 : 0;
14
+ return s <= 0 ? `${n}%` : `max(${n}%, ${X})`;
14
15
  }
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
+ function U({ granted: s, purchased: i, cycleTotal: n, tone: h, label: p }) {
17
+ return /* @__PURE__ */ t("div", { className: e.bar, "data-tone": h, role: "img", "aria-label": p, children: [
18
+ /* @__PURE__ */ a("span", { className: e.segmentGranted, "data-testid": "segment-granted", style: { width: P(s, n) } }),
19
+ /* @__PURE__ */ a("span", { className: e.segmentPurchased, "data-testid": "segment-purchased", style: { width: P(i, n) } })
19
20
  ] });
20
21
  }
21
- function J(i) {
22
- return i.totalOnly === !0 ? /* @__PURE__ */ a(W, { ...i }) : i.placement === "topbar" ? /* @__PURE__ */ a(M, { ...i }) : /* @__PURE__ */ a(I, { ...i });
22
+ function oe(s) {
23
+ return s.totalOnly === !0 ? /* @__PURE__ */ a(K, { ...s }) : s.placement === "topbar" ? /* @__PURE__ */ a(J, { ...s }) : /* @__PURE__ */ a(Q, { ...s });
23
24
  }
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 })
25
+ const x = 16;
26
+ function q(s, i) {
27
+ z(() => {
28
+ if (!i) return;
29
+ const n = s.current, h = n == null ? void 0 : n.querySelector("[data-token-popover]");
30
+ if (!n || !h) return;
31
+ const p = () => {
32
+ h.style.left = "";
33
+ const m = n.getBoundingClientRect().left, l = h.getBoundingClientRect(), g = l.right - (document.documentElement.clientWidth - x);
34
+ if (g <= 0) return;
35
+ const c = Math.max(l.left - g, x);
36
+ h.style.left = `${c - m}px`;
37
+ };
38
+ return p(), window.addEventListener("resize", p), () => window.removeEventListener("resize", p);
39
+ }, [s, i]);
40
+ }
41
+ function J({ granted: s = 0, purchased: i = 0, grantCycle: n, burnedFraction: h, grantExpires: p, burnNote: m, unknown: l = !1, onTopUp: g, labels: c, locale: d = $, walletHref: u, linkComponent: o, defaultOpen: f }) {
42
+ const r = w(c), b = G({ defaultOpen: f }), F = W(null);
43
+ q(F, b.open);
44
+ const R = o ?? "a", N = s + i, B = n !== void 0 && n > 0 ? (n - s) / n : 0, E = h ?? B, k = !l && E >= _, A = k && n !== void 0 ? n + i : N, C = k ? "threshold" : void 0, T = l ? "—" : v(N, d), I = () => r.bar(v(s, d), v(i, d), v(N, d)), L = k ? r.thresholdNote(j(E, d)) : void 0, S = l ? r.railBalanceUnknown : L ? `${r.railBalance(T)}. ${L}` : r.railBalance(T);
45
+ return /* @__PURE__ */ t("div", { ref: F, className: e.topRoot, "data-threshold": k ? "true" : void 0, children: [
46
+ /* @__PURE__ */ t("button", { type: "button", className: e.topTrigger, "aria-label": S, onClick: b.toggle, ...b.triggerProps, children: [
47
+ /* @__PURE__ */ t("span", { className: e.topFigure, "aria-hidden": "true", children: [
48
+ /* @__PURE__ */ a("span", { className: e.topAmount, children: T }),
49
+ /* @__PURE__ */ a("span", { className: e.topUnit, children: r.unit })
31
50
  ] }),
32
- !r && /* @__PURE__ */ a(T, { granted: i, purchased: l, total: F, className: e.topBar }),
33
- /* @__PURE__ */ a($, { className: e.topChevron })
51
+ !l && /* @__PURE__ */ a(O, { granted: s, purchased: i, total: A, tone: C, className: e.topBar }),
52
+ /* @__PURE__ */ a(M, { className: e.topChevron })
34
53
  ] }),
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 })
54
+ b.open && /* @__PURE__ */ t("div", { ...b.panelProps, className: e.popover, "data-token-popover": "", "aria-label": r.popover, children: [
55
+ /* @__PURE__ */ t("div", { className: e.popHead, children: [
56
+ /* @__PURE__ */ t("span", { className: e.popFigure, children: [
57
+ /* @__PURE__ */ a("span", { className: e.popAmount, children: T }),
58
+ /* @__PURE__ */ a("span", { className: e.popUnit, children: r.unit })
40
59
  ] }),
41
- c !== void 0 && /* @__PURE__ */ a(B, { className: y.quiet, href: c, onClick: d.close, children: s.open })
60
+ u !== void 0 && /* @__PURE__ */ a(R, { className: y.quiet, href: u, onClick: b.close, children: r.open })
42
61
  ] }),
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: [
62
+ l ? /* @__PURE__ */ a("p", { className: e.popNote, children: r.balanceUnknown }) : /* @__PURE__ */ t(Z, { children: [
63
+ /* @__PURE__ */ a(O, { granted: s, purchased: i, total: A, tone: C, className: e.popBar, label: I() }),
64
+ /* @__PURE__ */ t("ul", { className: e.legend, children: [
65
+ /* @__PURE__ */ t("li", { className: e.legendRow, children: [
47
66
  /* @__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 })
67
+ /* @__PURE__ */ t("span", { className: e.legendText, children: [
68
+ /* @__PURE__ */ a("span", { className: e.legendFigure, children: r.grantedFigure(v(s, d)) }),
69
+ /* @__PURE__ */ a("span", { className: e.legendNote, children: p ? r.grantedNote(p) : r.grantedNoteUndated })
51
70
  ] })
52
71
  ] }),
53
- /* @__PURE__ */ n("li", { className: e.legendRow, children: [
72
+ /* @__PURE__ */ t("li", { className: e.legendRow, children: [
54
73
  /* @__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 })
74
+ /* @__PURE__ */ t("span", { className: e.legendText, children: [
75
+ /* @__PURE__ */ a("span", { className: e.legendFigure, children: r.purchasedFigure(v(i, d)) }),
76
+ /* @__PURE__ */ a("span", { className: e.legendNote, children: r.purchasedNote })
58
77
  ] })
59
78
  ] })
60
79
  ] }),
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 })
80
+ (L || m || g !== void 0) && /* @__PURE__ */ t("div", { className: e.popFoot, children: [
81
+ L && /* @__PURE__ */ a("p", { className: e.popWarning, children: L }),
82
+ m && /* @__PURE__ */ a("p", { className: e.popNote, children: m }),
83
+ g !== void 0 && /* @__PURE__ */ a("button", { type: "button", className: `${y.primary} ${e.buy}`, "data-tone": "accent", onClick: g, children: r.buyTokens })
64
84
  ] })
65
85
  ] })
66
86
  ] })
67
87
  ] });
68
88
  }
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 })
89
+ function K({ balance: s, burnNote: i, onTopUp: n, labels: h, locale: p = $, walletHref: m, linkComponent: l, defaultOpen: g }) {
90
+ const c = w(h), d = G({ defaultOpen: g }), u = W(null);
91
+ q(u, d.open);
92
+ const o = l ?? "a", f = s < 0, r = v(f ? -s : s, p);
93
+ return /* @__PURE__ */ t("div", { ref: u, className: e.topRoot, "data-past-zero": f ? "true" : void 0, children: [
94
+ /* @__PURE__ */ t("button", { type: "button", className: e.topTrigger, "aria-label": f ? c.pastZeroBalance(r) : c.railBalance(r), onClick: d.toggle, ...d.triggerProps, children: [
95
+ /* @__PURE__ */ t("span", { className: e.topFigure, "aria-hidden": "true", children: [
96
+ /* @__PURE__ */ a("span", { className: e.topAmount, children: r }),
97
+ /* @__PURE__ */ a("span", { className: e.topUnit, children: f ? c.pastZero : c.unit })
76
98
  ] }),
77
- /* @__PURE__ */ a($, { className: e.topChevron })
99
+ /* @__PURE__ */ a(M, { className: e.topChevron })
78
100
  ] }),
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 })
101
+ d.open && /* @__PURE__ */ t("div", { ...d.panelProps, className: e.popover, "data-token-popover": "", "aria-label": c.popover, children: [
102
+ /* @__PURE__ */ t("div", { className: e.popHead, children: [
103
+ /* @__PURE__ */ t("span", { className: e.popFigure, children: [
104
+ /* @__PURE__ */ a("span", { className: e.popAmount, children: r }),
105
+ /* @__PURE__ */ a("span", { className: e.popUnit, children: f ? c.pastZeroLong : c.unit })
84
106
  ] }),
85
- v !== void 0 && /* @__PURE__ */ a(h, { className: y.quiet, href: v, onClick: g.close, children: c.open })
107
+ m !== void 0 && /* @__PURE__ */ a(o, { className: y.quiet, href: m, onClick: d.close, children: c.open })
86
108
  ] }),
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 })
109
+ (i || n !== void 0) && /* @__PURE__ */ t("div", { className: e.popFoot, children: [
110
+ i && /* @__PURE__ */ a("p", { className: e.popNote, children: i }),
111
+ n !== void 0 && /* @__PURE__ */ a("button", { type: "button", className: `${y.primary} ${e.buy}`, "data-tone": "accent", onClick: n, children: c.buyTokens })
90
112
  ] })
91
113
  ] })
92
114
  ] });
93
115
  }
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) } })
116
+ function O({ granted: s, purchased: i, total: n, tone: h, className: p, label: m }) {
117
+ return /* @__PURE__ */ t("span", { className: p, "data-tone": h, role: m ? "img" : void 0, "aria-label": m, "aria-hidden": m ? void 0 : "true", children: [
118
+ /* @__PURE__ */ a("span", { className: e.segmentGranted, "data-segment": "granted", style: { width: P(s, n) } }),
119
+ /* @__PURE__ */ a("span", { className: e.segmentPurchased, "data-segment": "purchased", style: { width: P(i, n) } })
98
120
  ] });
99
121
  }
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() })
122
+ function Q({ granted: s = 0, purchased: i = 0, grantCycle: n, burnedFraction: h, grantExpires: p, burnNote: m, unknown: l = !1, collapsed: g = !1, onTopUp: c, labels: d, locale: u = $ }) {
123
+ const o = w(d), f = () => o.bar(v(s, u), v(i, u), v(s + i, u)), r = s + i, b = (n ?? s) + i, F = n !== void 0 && n > 0 ? (n - s) / n : 0, R = h ?? F, N = !l && R >= _;
124
+ if (g) {
125
+ const B = l ? void 0 : o.railFigure(D(r, u));
126
+ return /* @__PURE__ */ t("div", { className: e.rail, role: "group", "aria-label": B === void 0 ? o.railBalanceUnknown : o.railBalance(B), tabIndex: 0, children: [
127
+ /* @__PURE__ */ a(H, { className: e.railIcon }),
128
+ /* @__PURE__ */ a("span", { className: e.railFigure, children: B ?? "—" }),
129
+ l ? /* @__PURE__ */ a("span", { className: e.srOnly, children: o.railUnknown }) : /* @__PURE__ */ a(U, { granted: s, purchased: i, cycleTotal: b, tone: N ? "threshold" : "rest", label: f() })
108
130
  ] });
109
131
  }
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),
132
+ return /* @__PURE__ */ t("div", { className: e.chip, role: "group", "aria-label": o.region, tabIndex: 0, "data-threshold": N ? "true" : void 0, "data-unknown": l ? "true" : void 0, children: [
133
+ /* @__PURE__ */ t("div", { className: e.header, children: [
134
+ /* @__PURE__ */ a("span", { className: e.name, children: o.name }),
135
+ N && /* @__PURE__ */ t("span", { className: e.pill, children: [
136
+ Math.round(R * 100),
115
137
  "%"
116
138
  ] })
117
139
  ] }),
118
- m ? /* @__PURE__ */ n("div", { className: e.figure, children: [
140
+ l ? /* @__PURE__ */ t("div", { className: e.figure, children: [
119
141
  /* @__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 })
142
+ /* @__PURE__ */ a(V, { className: e.retry }),
143
+ /* @__PURE__ */ a("span", { className: e.srOnly, children: o.balanceUnknown })
144
+ ] }) : /* @__PURE__ */ t("div", { className: e.figure, children: [
145
+ /* @__PURE__ */ a("span", { className: e.amount, children: v(r, u) }),
146
+ /* @__PURE__ */ a("span", { className: e.unit, children: o.unit })
125
147
  ] }),
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: [
148
+ l ? /* @__PURE__ */ a("div", { className: e.bar, "data-tone": "unknown", "aria-hidden": "true" }) : /* @__PURE__ */ a(U, { granted: s, purchased: i, cycleTotal: b, tone: N ? "threshold" : "rest", label: f() }),
149
+ !l && !N && /* @__PURE__ */ t("div", { className: e.details, children: [
150
+ /* @__PURE__ */ t("dl", { className: e.split, children: [
151
+ /* @__PURE__ */ t("div", { className: e.splitRow, children: [
152
+ /* @__PURE__ */ t("dt", { className: e.splitLabel, children: [
131
153
  /* @__PURE__ */ a("span", { className: e.dotGranted, "aria-hidden": "true" }),
132
- s.granted
154
+ o.granted
133
155
  ] }),
134
- /* @__PURE__ */ a("dd", { className: e.splitAmount, children: o(i, h) })
156
+ /* @__PURE__ */ a("dd", { className: e.splitAmount, children: v(s, u) })
135
157
  ] }),
136
- /* @__PURE__ */ n("div", { className: e.splitRow, children: [
137
- /* @__PURE__ */ n("dt", { className: e.splitLabel, children: [
158
+ /* @__PURE__ */ t("div", { className: e.splitRow, children: [
159
+ /* @__PURE__ */ t("dt", { className: e.splitLabel, children: [
138
160
  /* @__PURE__ */ a("span", { className: e.dotPurchased, "aria-hidden": "true" }),
139
- s.purchased
161
+ o.purchased
140
162
  ] }),
141
- /* @__PURE__ */ a("dd", { className: e.splitAmount, children: o(l, h) })
163
+ /* @__PURE__ */ a("dd", { className: e.splitAmount, children: v(i, u) })
142
164
  ] })
143
165
  ] }),
144
- r && /* @__PURE__ */ a("p", { className: e.footer, children: s.grantExpiry(r) })
166
+ p && /* @__PURE__ */ a("p", { className: e.footer, children: o.grantExpiry(p) })
145
167
  ] }),
146
- N && v && /* @__PURE__ */ a("p", { className: e.burnNote, children: v }),
147
- !m && c !== void 0 && /* @__PURE__ */ a(
168
+ N && m && /* @__PURE__ */ a("p", { className: e.burnNote, children: m }),
169
+ !l && c !== void 0 && /* @__PURE__ */ a(
148
170
  "button",
149
171
  {
150
172
  type: "button",
@@ -152,12 +174,12 @@ function I({ granted: i = 0, purchased: l = 0, grantCycle: t, burnedFraction: p,
152
174
  "data-tone": N ? "accent" : void 0,
153
175
  "data-grown": N ? "true" : void 0,
154
176
  onClick: c,
155
- children: s.topUp
177
+ children: o.topUp
156
178
  }
157
179
  )
158
180
  ] });
159
181
  }
160
182
  export {
161
- J as WalletChip
183
+ oe as WalletChip
162
184
  };
163
185
  //# sourceMappingURL=WalletChip.js.map