@nxgt/material 3.48.0 → 3.49.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 (83) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -2
  3. package/dist/{button-yaltbQmC.js → button-DJgaQbBD.js} +49 -49
  4. package/dist/charts.js +144 -144
  5. package/dist/{chip-BqWbbr1b.js → chip-DN44R1vW.js} +56 -56
  6. package/dist/{code-editor-C9qBNoYb.js → code-editor-BJ9ewxSC.js} +307 -307
  7. package/dist/code-editor.js +46 -46
  8. package/dist/{code-language-items-DAHtfQ7W.js → code-language-items-BJE3VuQg.js} +1 -1
  9. package/dist/components/components.css +1 -0
  10. package/dist/components/ui/actions/action-card/action-card-indicator.css +48 -0
  11. package/dist/components/ui/actions/action-card/action-card-modes.css +4 -1
  12. package/dist/components/ui/actions/action-card/action-card-tile.css +141 -0
  13. package/dist/components/ui/actions/action-card/action-card.css +33 -3
  14. package/dist/{components-Ox6FHmpx.js → components-AtBccCir.js} +17842 -17879
  15. package/dist/components.js +23 -23
  16. package/dist/{dialog-CCCcnTIx.js → dialog-ODql4vH7.js} +15 -15
  17. package/dist/{tooltip-CkttDIab.js → dist-B61_o9Mg.js} +69 -66
  18. package/dist/dnd.js +1 -1
  19. package/dist/{dropdown-menu-Df8785nt.js → dropdown-menu-DRXYP9ta.js} +274 -274
  20. package/dist/editor.js +1027 -1027
  21. package/dist/{empty-state-DcF4TBzi.js → empty-state-C9QqvBU1.js} +36 -36
  22. package/dist/{escape-owner-C4W_sOAU.js → escape-owner-DCrlERLM.js} +1 -1
  23. package/dist/{field-blur-CJHzVSh9.js → field-blur-DYGyIdfD.js} +1 -1
  24. package/dist/{field-blur-context-Cft9s7Hg.js → field-blur-context-B-fSpl1H.js} +1 -1
  25. package/dist/hooks.js +2 -2
  26. package/dist/{hover-card-C0fw2kLK.js → hover-card-EO_CckIx.js} +19 -19
  27. package/dist/{icon-badge-aJ22mKGh.js → icon-badge-BQYj_LE6.js} +3 -3
  28. package/dist/{icon-button-CN9r5TNE.js → icon-button-B481L2TP.js} +20 -20
  29. package/dist/lib/components/ui/actions/action-card/action-card-semantics.d.ts +25 -2
  30. package/dist/lib/components/ui/actions/action-card/action-card.d.ts +18 -2
  31. package/dist/lib/components/ui/actions/action-card/partials/action-card-icon.d.ts +6 -0
  32. package/dist/lib/components/ui/actions/action-card/partials/action-card-meta.d.ts +15 -0
  33. package/dist/lib/components/ui/actions/action-card/partials/action-card-status.d.ts +6 -0
  34. package/dist/lib/components/ui/actions/action-card/partials/action-card-text.d.ts +20 -0
  35. package/dist/lib/components/ui/actions/action-card/partials/action-card-title-button.d.ts +14 -0
  36. package/dist/lib/components/ui/actions/action-card/partials/action-card-trail.d.ts +6 -0
  37. package/dist/lib/components/ui/actions/action-card/use-action-card-names.d.ts +22 -0
  38. package/dist/lib/components/ui/actions/action-card/use-reveal.d.ts +23 -0
  39. package/dist/lib/components/ui/actions/button/button.variants.d.ts +1 -1
  40. package/dist/lib/components/ui/actions/icon-button/icon-button.variants.d.ts +1 -1
  41. package/dist/lib/components/ui/collections/row-menu/row-menu.d.ts +1 -1
  42. package/dist/lib/components/ui/dates/duration-field/partials/use-duration-box.d.ts +1 -1
  43. package/dist/lib/components/ui/display/badge/badge.d.ts +1 -1
  44. package/dist/lib/components/ui/display/day-separator/day-separator.d.ts +1 -1
  45. package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
  46. package/dist/lib/components/ui/fields/slider/split-slider-props.d.ts +20 -20
  47. package/dist/lib/components/ui/fields/slider/use-slider-control.d.ts +20 -20
  48. package/dist/lib/components/ui/layout/app-shell/route-transition.d.ts +1 -1
  49. package/dist/lib/components/ui/media/carousel/use-carousel-engine.d.ts +1 -1
  50. package/dist/lib/components/ui/media/media-player/engine/use-queue-actions.d.ts +1 -1
  51. package/dist/lib/components/ui/media/pdf-reader/pdf-reader.slice.d.ts +1 -1
  52. package/dist/lib/components/ui/selection/choice-group/use-choice-group-field.d.ts +34 -34
  53. package/dist/lib/components/ui/widgets/chat/chat-message.variants.d.ts +2 -2
  54. package/dist/lib/components/ui/widgets/event-calendar/use-event-calendar.d.ts +1 -1
  55. package/dist/lib/i18n/translator.d.ts +1 -1
  56. package/dist/main.js +30 -30
  57. package/dist/map.js +78 -78
  58. package/dist/material.css +1 -1
  59. package/dist/nxgt-theme-ivgNca3z.js +37 -0
  60. package/dist/pdf-reader.js +1 -1
  61. package/dist/{public-zVb_Nq_D.js → public-CZBz4JVu.js} +70 -70
  62. package/dist/{rich-code-block-DMWZZJma.js → rich-code-block-597e0_Qm.js} +51 -51
  63. package/dist/{sortable-provider-DstbgMVf.js → sortable-provider-CK_xAk2H.js} +217 -217
  64. package/dist/{spinner-C4CgDEYm.js → spinner-BhuZuHK1.js} +1 -1
  65. package/dist/theme-picker.js +45 -45
  66. package/dist/{theme-store-CSl51uNH.js → theme-store-BdPp43cV.js} +13 -13
  67. package/dist/{theme-toggle-CGW2_K54.js → theme-toggle-Dnjn83TJ.js} +15 -15
  68. package/dist/themes.js +17 -17
  69. package/dist/{toggle-group-BMJNcFAC.js → toggle-group-BkH23Jk4.js} +11 -11
  70. package/dist/{toolbar-items-CsLGJMEJ.js → toolbar-items-CCwIu7fE.js} +426 -426
  71. package/dist/{use-chat-composer-Brcb5f7r.js → use-chat-composer-Ot5XUbdn.js} +5138 -4908
  72. package/dist/{use-theme-DMcyJ52N.js → use-theme-BCLireTd.js} +1 -1
  73. package/docs/components/buttons-and-actions.md +62 -4
  74. package/docs/components/data-table-filter-and-lists.md +1 -1
  75. package/docs/guides/cards-and-tiles.md +60 -0
  76. package/docs/roadmap.md +11 -0
  77. package/lib/components/components.css +1 -0
  78. package/lib/components/ui/actions/action-card/action-card-indicator.css +48 -0
  79. package/lib/components/ui/actions/action-card/action-card-modes.css +4 -1
  80. package/lib/components/ui/actions/action-card/action-card-tile.css +141 -0
  81. package/lib/components/ui/actions/action-card/action-card.css +33 -3
  82. package/package.json +1 -1
  83. package/dist/nxgt-theme-ZS945iMP.js +0 -37
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./use-ssr-media-query-C6M5m8sf.js";
2
- import { i as t, n, o as r, r as i, s as a, t as o } from "./theme-store-CSl51uNH.js";
2
+ import { i as t, n, o as r, r as i, s as a, t as o } from "./theme-store-BdPp43cV.js";
3
3
  import { a as s } from "./theme-context-Cofk6vgs.js";
4
4
  import { useCallback as c, useEffect as l, useState as u, useSyncExternalStore as d } from "react";
5
5
  import { PRESET_SCHEMES as f } from "@nxgt/material-core/theme/boot";
@@ -20,7 +20,7 @@ and language switches. Everything is imported from `@nxgt/material/components`.
20
20
  | <img src="../previews/buttons-actions-loadmorebutton.webp" width="96" alt=""> | [LoadMoreButton](#loadmorebutton) | "Load more" for cursor pagination |
21
21
  | <img src="../previews/buttons-actions-scrolltotop.webp" width="96" alt=""> | [ScrollToTop](#scrolltotop) | Appears past a scroll threshold |
22
22
  | <img src="../previews/buttons-actions-scrolltolatestbutton.webp" width="96" alt=""> | [ScrollToLatestButton](#scrolltolatestbutton) | "Jump to latest" over a scroll box, counting what arrived |
23
- | <img src="../previews/buttons-actions-actioncard.webp" width="96" alt=""> | [ActionCard](#actioncard) | Clickable card, a button (`aria-pressed`) when it chooses or reacts, with an active indicator |
23
+ | <img src="../previews/buttons-actions-actioncard.webp" width="96" alt=""> | [ActionCard](#actioncard) | Clickable card, a button (`aria-pressed`) when it chooses or reacts, with an active indicator; `status`, `meta`, a trailing `action` and a `tile` variant |
24
24
  | <img src="../previews/buttons-actions-themetoggle.webp" width="96" alt=""> | [ThemeToggle](#themetoggle) | Light / dark / system switch |
25
25
  | <img src="../previews/buttons-actions-languageswitcher.webp" width="96" alt=""> | [LanguageSwitcher](#languageswitcher) | Menu of the `I18nProvider` languages |
26
26
 
@@ -1063,9 +1063,12 @@ import { Banknote, CreditCard } from 'lucide-react';
1063
1063
  | `active` | `boolean` | — | the chosen look: a primary container with its edge, a primary title, the icon's circle morphs to a filled cookie and the indicator fills; also `aria-pressed` |
1064
1064
  | `onClick` | `(event) => void` | — | makes the card a button |
1065
1065
  | `disabled` | `boolean` | `false` | `aria-disabled`, out of the Tab order, no click and no key, muted look |
1066
- | `variant` | `'sm' \| 'md'` | `'sm'` | one row, or icon and indicator above the text |
1067
- | `withIndicator` | `boolean` | `true` | the radio-like ring that fills with a check |
1066
+ | `variant` | `'sm' \| 'md' \| 'tile'` | `'sm'` | one row, icon and indicator above the text, or a compact [tile](#actioncard-tile) |
1067
+ | `withIndicator` | `boolean` | `true` (`false` for `tile`) | the radio-like ring that fills with a check |
1068
1068
  | `title`, `description`, `icon` | `ReactNode` | — | the content |
1069
+ | `status` | `ReactNode` | — | a line under the title; a string or number becomes a soft `Badge`, a node is shown as given |
1070
+ | `meta` | `ReactNode` | — | a secondary line, one line with an ellipsis |
1071
+ | `action` | `ReactNode` | — | a trailing control outside the press surface, see [tile](#actioncard-tile); `title` is then required, a `role` moves to the title button; the card's `disabled` does not reach it, disable its control too |
1069
1072
 
1070
1073
  A card with `active`, `onClick`, `disabled` or your own `role` is `role="button"` (unless you set another): it takes the Tab stop, and
1071
1074
  Enter and Space press it. `active` sets `aria-pressed`; pass your own `role`
@@ -1079,9 +1082,64 @@ the card, forced colours in system colours, and no motion under reduced motion.
1079
1082
  For a card choice bound to a form value, see `ChoiceCardGroup` on
1080
1083
  [Selection & choice](selection-and-choice.md).
1081
1084
 
1085
+ ### ActionCard tile
1086
+
1087
+ `variant="tile"` is a compact grid cell for boards: no minimum width (it fills
1088
+ its grid track), the title and the `action` on the first row, then `status`,
1089
+ `description` and `meta`, and no indicator unless `withIndicator`. `status` and
1090
+ `meta` work on every variant.
1091
+
1092
+ ```tsx
1093
+ import {
1094
+ ActionCard,
1095
+ Badge,
1096
+ DropdownMenuRadioGroup,
1097
+ DropdownMenuRadioItem,
1098
+ RowMenu,
1099
+ } from '@nxgt/material/components';
1100
+
1101
+ <ActionCard
1102
+ variant="tile"
1103
+ active={selected === unit.id}
1104
+ onClick={() => setSelected(unit.id)}
1105
+ title={unit.name}
1106
+ status={<Badge variant="soft" tone="success">Free</Badge>}
1107
+ meta="Zone B, second floor"
1108
+ action={
1109
+ <RowMenu
1110
+ label={unit.name}
1111
+ triggerProps={{ 'aria-label': `Change status of ${unit.name}` }}
1112
+ >
1113
+ <DropdownMenuRadioGroup value={unit.status} onValueChange={setStatus}>
1114
+ <DropdownMenuRadioItem value="free">Free</DropdownMenuRadioItem>
1115
+ <DropdownMenuRadioItem value="occupied">Occupied</DropdownMenuRadioItem>
1116
+ </DropdownMenuRadioGroup>
1117
+ </RowMenu>
1118
+ }
1119
+ />;
1120
+ ```
1121
+
1122
+ With an `action`, a card that chooses or reacts is a plain `div` and its
1123
+ **title is the one button**, stretched over the card, so the whole card presses
1124
+ it and the action never nests inside it (no `nested-interactive`). The button
1125
+ is named after the title, the status and the meta together ("Unit 21 Free Zone
1126
+ B"); the action keeps its own name. The card is one Tab stop and the action a
1127
+ second; Enter and Space press the button. `disabled` disables the button
1128
+ natively; disable the action's control too. **`title` is required with
1129
+ `action`**: it is the button's text (without one the button is still there, named
1130
+ after the status and the meta line, and development builds warn). The
1131
+ `description` is the button's description (`aria-describedby`). A `role`
1132
+ (`switch`, `checkbox`, `radio`) and its `aria-checked` move to the button, where
1133
+ they are valid; the root stays a plain `div` and takes no `aria-checked` or
1134
+ `aria-label`. Hover and press answer only the title button (its stretched area covers the
1135
+ card, padding included), not the action. The meta line shows its full text in a tooltip, on hover or
1136
+ keyboard focus of the title button, only while it is clipped (Escape dismisses
1137
+ it; moving the pointer across the line does not). Without `action` the DOM is as
1138
+ before. Nothing is added for a Vue port yet (React first).
1139
+
1082
1140
  The root is `data-slot="action-card"` (it was the `Card` primitive's `data-slot="card"`): style it with `className`, not through `Card` classes or a `[data-slot=card]` selector.
1083
1141
 
1084
- **Storybook:** `Buttons & actions/ActionCard`, `Buttons & actions/ActionCard/Look` · **Vue:** `ActionCard`, with the earlier look and no button role yet (#1195)
1142
+ A whole board built on it, with sections and an occupancy table, is the `Guides/Recipes/Status board` recipe. **Storybook:** `Buttons & actions/ActionCard`, `Buttons & actions/ActionCard/Look`, `Buttons & actions/ActionCard/Tile`, `Buttons & actions/ActionCard/Checks` · **Vue:** `ActionCard`, with the earlier look and no button role yet (#1195)
1085
1143
 
1086
1144
  ---
1087
1145
 
@@ -1169,7 +1169,7 @@ and `ref`, so it is the child of a `DropdownMenuTrigger asChild`.
1169
1169
  | --- | --- | --- | --- |
1170
1170
  | `label` (`RowMenu`, `RowMenuTrigger`) | `string` | — | the row's name; the button's name is "Actions for {label}" (translated). An `aria-label` of your own wins |
1171
1171
  | `items` (`RowMenu`) | `{ label, icon?, onSelect?, disabled?, destructive?, id? }[]` | `[]` | the actions; `destructive` ones are drawn in the error colour and moved last, after a separator |
1172
- | `children` (`RowMenu`) | `ReactNode` | — | menu content of your own, above `items` (put a destructive item last yourself) |
1172
+ | `children` (`RowMenu`) | `ReactNode` | — | menu content of your own, above `items` (put a destructive item last yourself); its menu items are 44px high on a coarse pointer too |
1173
1173
  | `triggerProps` (`RowMenu`) | button props | — | `disabled`, `className`, `data-*` on the button |
1174
1174
  | `open`, `onOpenChange` (`RowMenu`) | as `DropdownMenu` | — | controlled state |
1175
1175
  | `label`, `items`, `menu` (`rowMenuColumn`) | `(row) => string` / `(row) => RowMenuItem[]` / `(row) => ReactNode` | — | the row's name, its actions as data, or its menu content as nodes |
@@ -240,6 +240,66 @@ navigation to learn.
240
240
 
241
241
  A `linkComponent` must forward `onClick` (with `className`): it is how `onRowClick` runs before the card's link navigates. A click that opens the link elsewhere (Ctrl, Cmd, Shift, Alt, the middle button) only opens it: `onRowClick` does not run. A title that is a button (`onRowClick` and no href) runs it on every click.
242
242
 
243
+ ## Status tiles and boards
244
+
245
+ A board of resources (beds, rooms, vehicles) is not a list of records: it is a
246
+ grid of compact cells you read at a glance and change in place. Use
247
+ [`ActionCard variant="tile"`](../components/buttons-and-actions.md#actioncard-tile)
248
+ in a `ResponsiveGrid minItem="xs"`, one grid per section under its own `h2`:
249
+
250
+ - **`status`** is a soft `Badge` with its word and an icon, so a status is
251
+ never told by colour alone.
252
+ - **`meta`** is one line, the occupant only while occupied; a long one is
253
+ clipped and shown in full in a tooltip.
254
+ - **`action`** is a `RowMenu` with a `DropdownMenuRadioGroup` of statuses,
255
+ named "Change status of {name}". The title is the one button (it opens the
256
+ detail), so the card and its menu are two tab stops and nothing nests.
257
+
258
+ ```tsx
259
+ import {
260
+ ActionCard,
261
+ Badge,
262
+ DropdownMenuRadioGroup,
263
+ DropdownMenuRadioItem,
264
+ ResponsiveGrid,
265
+ RowMenu,
266
+ } from '@nxgt/material/components';
267
+
268
+ <ResponsiveGrid minItem="xs">
269
+ <ActionCard
270
+ variant="tile"
271
+ title="Bed A1"
272
+ status={<Badge variant="soft" tone="warning" icon="user">Occupied</Badge>}
273
+ meta="Amara Diallo"
274
+ onClick={() => openDetail('a1')}
275
+ action={
276
+ <RowMenu
277
+ label="Bed A1"
278
+ triggerProps={{ 'aria-label': 'Change status of Bed A1' }}
279
+ >
280
+ <DropdownMenuRadioGroup value={status} onValueChange={setStatus}>
281
+ <DropdownMenuRadioItem value="free">Free</DropdownMenuRadioItem>
282
+ <DropdownMenuRadioItem value="occupied">Occupied</DropdownMenuRadioItem>
283
+ <DropdownMenuRadioItem value="cleaning">Cleaning</DropdownMenuRadioItem>
284
+ </DropdownMenuRadioGroup>
285
+ </RowMenu>
286
+ }
287
+ />
288
+ </ResponsiveGrid>;
289
+ ```
290
+
291
+ `title` is required with `action`: it is the card's button, named after the
292
+ title, the status and the meta line.
293
+
294
+ For the figures of the whole board, put a `StatCardGroup` above a `DataTable`
295
+ with one row per section, one numeric column per status (they add up to the
296
+ total) (`meta: { numeric: true }`) and a
297
+ rate cell (a `Progress` named "{section} occupancy" beside the visible
298
+ percent); `layout={{ phone: 'tiles', wide: 'table' }}` turns the rows into
299
+ tiles on a phone. Both screens, tested at 360 and 1440 px, light and dark, are
300
+ the `Guides/Recipes/Status board` story, and the Claude Code plugin's
301
+ `screen-recipes` skill ships their code.
302
+
243
303
  ## Troubleshooting
244
304
 
245
305
  **The sort control is missing, or an option reads like the column id.** The control needs a column that can be sorted (an accessor, `enableSorting` not `false`); an option is the column's `meta.label`, else a string `header`. Set `meta.label`.
package/docs/roadmap.md CHANGED
@@ -330,6 +330,17 @@ version they shipped in, and planned entries may name the major they target.
330
330
 
331
331
  ## Shipped
332
332
 
333
+ - **A status board of tiles** (3.49.0) — `ActionCard` gains `status` (a soft badge line),
334
+ `meta` (one line, its tooltip only while clipped), a trailing `action` (a
335
+ `RowMenu`, an `IconButton`) outside the press surface, and `variant="tile"`
336
+ for grids of compact cells. With an `action` the title is the card's one
337
+ button, so the card and its menu are two tab stops and nothing nests. The
338
+ `Guides/Recipes/Status board` recipe (tiles in sections with a menu that
339
+ changes the status, and an occupancy table with a rate per section) shows
340
+ the whole pattern, with its code in the plugin's `screen-recipes` skill.
341
+ React only for now; the Vue gap is a `vue` issue.
342
+ ([ActionCard tile](components/buttons-and-actions.md#actioncard-tile))
343
+
333
344
  - **A refused field says why** (3.48.0) — the filter bar shows the words of a
334
345
  refused field under it, in one error `Alert`: "Period: choose 366 days or
335
346
  fewer.", after `formError`, so a refused, empty list no longer shows a red
@@ -191,6 +191,7 @@
191
191
  @import "./ui/feedback/toast/toast-tokens.css";
192
192
  @import "./ui/actions/action-card/action-card.css";
193
193
  @import "./ui/actions/action-card/action-card-indicator.css";
194
+ @import "./ui/actions/action-card/action-card-tile.css";
194
195
  @import "./ui/actions/action-card/action-card-modes.css";
195
196
  @import "./ui/media/galleries/gallery-image-lists.css";
196
197
  /* Gallery: the View Transition from a tile to its lightbox. */
@@ -37,4 +37,52 @@
37
37
  .nxgt-action-card[data-active] .nxgt-action-card-indicator svg {
38
38
  stroke-dashoffset: 0;
39
39
  }
40
+
41
+ /* The indicator takes its own column, after the action, only when shown. */
42
+ .nxgt-action-card[data-size="tile"]:has(> .nxgt-action-card-indicator) {
43
+ grid-template-columns: minmax(0, 1fr) auto;
44
+ grid-template-areas: "title ind" "status status" "desc desc" "meta meta";
45
+ }
46
+ .nxgt-action-card[data-size="tile"][data-icon]:has(
47
+ > .nxgt-action-card-indicator
48
+ ) {
49
+ grid-template-columns: auto minmax(0, 1fr) auto;
50
+ grid-template-areas:
51
+ "icon title ind"
52
+ ". status status"
53
+ ". desc desc"
54
+ ". meta meta";
55
+ }
56
+ .nxgt-action-card[data-size="tile"][data-has-action]:has(
57
+ > .nxgt-action-card-indicator
58
+ ) {
59
+ grid-template-columns: minmax(0, 1fr) auto auto;
60
+ grid-template-areas:
61
+ "title act ind"
62
+ "status status status"
63
+ "desc desc desc"
64
+ "meta meta meta";
65
+ }
66
+ .nxgt-action-card[data-size="tile"][data-has-action][data-icon]:has(
67
+ > .nxgt-action-card-indicator
68
+ ) {
69
+ grid-template-columns: auto minmax(0, 1fr) auto auto;
70
+ grid-template-areas:
71
+ "icon title act ind"
72
+ ". status status status"
73
+ ". desc desc desc"
74
+ ". meta meta meta";
75
+ }
76
+
77
+ /* The indicator is centred on the title row (36px high). */
78
+ .nxgt-action-card[data-size="tile"] .nxgt-action-card-indicator {
79
+ align-self: start;
80
+ margin-block: 5px;
81
+ }
82
+
83
+ /* The action is no longer at the card's edge: no optical offset. */
84
+ .nxgt-action-card[data-size="tile"]:has(> .nxgt-action-card-indicator)
85
+ .nxgt-action-card-action {
86
+ margin-inline-end: 0;
87
+ }
40
88
  }
@@ -7,7 +7,10 @@
7
7
  .nxgt-action-card * {
8
8
  transition: none;
9
9
  }
10
- .nxgt-action-card[data-interactive]:not([data-disabled]):active {
10
+ .nxgt-action-card[data-interactive]:not([data-disabled]):active,
11
+ .nxgt-action-card[data-has-action][data-interactive]:not(
12
+ [data-disabled]
13
+ ):has(.nxgt-action-card-button:active) {
11
14
  scale: none;
12
15
  --ac-r: 12px;
13
16
  }
@@ -0,0 +1,141 @@
1
+ /* biome-ignore-all lint/style/noDescendingSpecificity: states are grouped by meaning, not by specificity */
2
+ /* ActionCard status, meta, action and the tile variant. Loaded after
3
+ * action-card.css and the indicator. With an `action` the title is the card's
4
+ * one button: its ::after covers the card, and the action sits above it. */
5
+ @layer components {
6
+ .nxgt-action-card-status {
7
+ display: flex;
8
+ margin-top: 4px;
9
+ min-width: 0;
10
+ }
11
+ .nxgt-action-card-meta {
12
+ display: block;
13
+ margin-top: 2px;
14
+ min-width: 0;
15
+ overflow: hidden;
16
+ white-space: nowrap;
17
+ text-overflow: ellipsis;
18
+ font-size: 0.8125rem;
19
+ line-height: 1.4;
20
+ color: color-mix(in oklab, var(--card-foreground) 70%, var(--card));
21
+ }
22
+
23
+ /* The title button: the card's press surface. */
24
+ .nxgt-action-card-button {
25
+ display: inline;
26
+ margin: 0;
27
+ padding: 0;
28
+ border: 0;
29
+ background: none;
30
+ color: inherit;
31
+ font: inherit;
32
+ letter-spacing: inherit;
33
+ text-align: start;
34
+ cursor: pointer;
35
+ outline: none;
36
+ }
37
+ .nxgt-action-card-button::after {
38
+ content: "";
39
+ position: absolute;
40
+ inset: 0;
41
+ border-radius: inherit;
42
+ z-index: 0;
43
+ }
44
+ .nxgt-action-card-button:disabled {
45
+ cursor: not-allowed;
46
+ }
47
+ .nxgt-action-card:has(.nxgt-action-card-button:focus-visible) {
48
+ outline: 3px solid var(--ac-ring);
49
+ outline-offset: -3px;
50
+ }
51
+
52
+ /* The action: its own grid area, above the stretched button. */
53
+ .nxgt-action-card-action {
54
+ grid-area: act;
55
+ position: relative;
56
+ z-index: 1;
57
+ justify-self: end;
58
+ display: inline-flex;
59
+ margin-inline-end: -8px;
60
+ }
61
+ .nxgt-action-card[data-has-action] {
62
+ grid-template-columns: auto minmax(0, 1fr) auto auto;
63
+ grid-template-areas: "icon text act ind";
64
+ }
65
+ .nxgt-action-card[data-has-action][data-size="md"] {
66
+ grid-template-columns: auto minmax(0, 1fr) auto;
67
+ grid-template-areas: "icon act ind" "text text text";
68
+ }
69
+ .nxgt-action-card[data-has-action][data-size="md"]:not([data-icon]) {
70
+ grid-template-columns: minmax(0, 1fr) auto auto;
71
+ grid-template-areas: "text act ind";
72
+ }
73
+
74
+ /* Tile: a compact grid cell, title and action on the first row, then the
75
+ * status, the description and the meta line, each full width. The text
76
+ * wrapper dissolves so its children take the areas. */
77
+ .nxgt-action-card[data-size="tile"] {
78
+ grid-template-columns: minmax(0, 1fr) auto;
79
+ grid-template-areas: "title act" "status status" "desc desc" "meta meta";
80
+ align-items: start;
81
+ /* A taller neighbour stretches the card: keep the rows at the top. */
82
+ align-content: start;
83
+ row-gap: 0;
84
+ column-gap: 8px;
85
+ min-height: 0;
86
+ min-width: 0;
87
+ padding-block: 12px;
88
+ padding-inline: 16px 12px;
89
+ }
90
+ .nxgt-action-card[data-size="tile"][data-icon] {
91
+ grid-template-columns: auto minmax(0, 1fr) auto;
92
+ grid-template-areas:
93
+ "icon title act"
94
+ ". status status"
95
+ ". desc desc"
96
+ ". meta meta";
97
+ }
98
+ .nxgt-action-card[data-size="tile"] .nxgt-action-card-icon {
99
+ width: 36px;
100
+ height: 36px;
101
+ }
102
+ .nxgt-action-card[data-size="tile"] .nxgt-action-card-text {
103
+ display: contents;
104
+ }
105
+ .nxgt-action-card[data-size="tile"] .nxgt-action-card-title {
106
+ grid-area: title;
107
+ align-self: center;
108
+ min-height: 36px;
109
+ display: flex;
110
+ align-items: center;
111
+ }
112
+ .nxgt-action-card[data-size="tile"] .nxgt-action-card-description {
113
+ grid-area: desc;
114
+ margin-top: 2px;
115
+ }
116
+ .nxgt-action-card[data-size="tile"] .nxgt-action-card-status {
117
+ grid-area: status;
118
+ }
119
+ .nxgt-action-card[data-size="tile"] .nxgt-action-card-meta {
120
+ grid-area: meta;
121
+ }
122
+ .nxgt-action-card[data-size="tile"][data-has-action]
123
+ .nxgt-action-card-action {
124
+ align-self: start;
125
+ }
126
+
127
+ @media (forced-colors: active) {
128
+ .nxgt-action-card:has(.nxgt-action-card-button:focus-visible) {
129
+ outline: 3px solid CanvasText;
130
+ outline-offset: -5px;
131
+ }
132
+ .nxgt-action-card-meta {
133
+ color: CanvasText;
134
+ }
135
+ /* a chosen tile's border is 2px here: the content keeps its place */
136
+ .nxgt-action-card[data-size="tile"][data-active] {
137
+ padding-block: 11px;
138
+ padding-inline: 15px 11px;
139
+ }
140
+ }
141
+ }
@@ -125,13 +125,43 @@
125
125
  .nxgt-action-card[data-interactive]:not([data-disabled]) {
126
126
  cursor: pointer;
127
127
  }
128
- .nxgt-action-card[data-interactive]:not([data-disabled]):hover {
128
+ .nxgt-action-card[data-interactive]:not(
129
+ [data-has-action],
130
+ [data-disabled]
131
+ ):hover {
129
132
  --ac-tint: 11%;
130
133
  }
131
- .nxgt-action-card[data-interactive][data-active]:not([data-disabled]):hover {
134
+ .nxgt-action-card[data-interactive][data-active]:not(
135
+ [data-has-action],
136
+ [data-disabled]
137
+ ):hover {
132
138
  --ac-tint: 21%;
133
139
  }
134
- .nxgt-action-card[data-interactive]:not([data-disabled]):active {
140
+ .nxgt-action-card[data-interactive]:not(
141
+ [data-has-action],
142
+ [data-disabled]
143
+ ):active {
144
+ --ac-tint: 15%;
145
+ --ac-r: 16px;
146
+ scale: 0.97;
147
+ }
148
+
149
+ /* With an action, only the title button answers hover and press (its
150
+ * stretched ::after covers the card, padding included); the action does
151
+ * not. The rules above leave these cards to the ones below. */
152
+ .nxgt-action-card[data-has-action][data-interactive]:not([data-disabled]):has(
153
+ .nxgt-action-card-button:hover
154
+ ) {
155
+ --ac-tint: 11%;
156
+ }
157
+ .nxgt-action-card[data-has-action][data-interactive][data-active]:not(
158
+ [data-disabled]
159
+ ):has(.nxgt-action-card-button:hover) {
160
+ --ac-tint: 21%;
161
+ }
162
+ .nxgt-action-card[data-has-action][data-interactive]:not([data-disabled]):has(
163
+ .nxgt-action-card-button:active
164
+ ) {
135
165
  --ac-tint: 15%;
136
166
  --ac-r: 16px;
137
167
  scale: 0.97;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/material",
3
- "version": "3.48.0",
3
+ "version": "3.49.0",
4
4
  "license": "MIT",
5
5
  "bugs": {
6
6
  "email": "stevegires@gmail.com"
@@ -1,37 +0,0 @@
1
- import { t as e } from "./dist-DVRQkaTK.js";
2
- import { t } from "./is-production-GLw59WU8.js";
3
- import { n, r, t as i } from "./theme-context-Cofk6vgs.js";
4
- import { t as a } from "./warn-once-C_e47JM8.js";
5
- import { useContext as o, useMemo as s } from "react";
6
- import { jsx as c } from "react/jsx-runtime";
7
- //#region lib/themes/theme-value.ts
8
- function l(e, t, n) {
9
- return {
10
- name: e,
11
- theme: t,
12
- background: t?.background === !1 ? !1 : t?.background ?? i,
13
- defaultMode: n
14
- };
15
- }
16
- //#endregion
17
- //#region lib/themes/nxgt-theme.tsx
18
- function u({ theme: i, mode: u, asChild: d = !1, children: f, ...p }) {
19
- let m = o(r), h = typeof i == "string" ? m?.find((e) => e.name === i) : i, g = typeof i == "string" ? i : i.name;
20
- !t() && m && !h && a(`theme "${g}" is not in the provider's themes; its background is the default.`, "NxgtTheme");
21
- let _ = o(n)?.defaultMode, v = s(() => l(g, h, _), [
22
- g,
23
- h,
24
- _
25
- ]), y = d ? e : "div";
26
- return /* @__PURE__ */ c(n.Provider, {
27
- value: v,
28
- children: /* @__PURE__ */ c(y, {
29
- ...p,
30
- "data-nxgt-theme": g,
31
- ...u ? { "data-theme": u } : {},
32
- children: f
33
- })
34
- });
35
- }
36
- //#endregion
37
- export { l as n, u as t };