laif-ds 1.0.0 → 1.0.2-app-data-grid.76

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 (76) hide show
  1. package/dist/CHANGELOG.md +282 -0
  2. package/dist/_virtual/index7.js +5 -2
  3. package/dist/_virtual/index8.js +2 -5
  4. package/dist/agent-docs/adoption-report.json +164 -83
  5. package/dist/agent-docs/components/AppBottomNav.md +180 -49
  6. package/dist/agent-docs/components/AppCard.md +25 -21
  7. package/dist/agent-docs/components/AppDataGrid.md +2602 -0
  8. package/dist/agent-docs/components/AppEditor.md +18 -13
  9. package/dist/agent-docs/components/AppSelect.md +50 -0
  10. package/dist/agent-docs/components/AppSidebar.md +504 -11
  11. package/dist/agent-docs/components/DataTable.md +34 -3
  12. package/dist/agent-docs/components/DatePicker.md +7 -7
  13. package/dist/agent-docs/components/FileUploader.md +12 -12
  14. package/dist/agent-docs/components/GridFilterPanel.md +112 -0
  15. package/dist/agent-docs/components/Sidebar.md +72 -1
  16. package/dist/agent-docs/components/SidebarMenuBadge.md +87 -0
  17. package/dist/agent-docs/components-list.md +47 -2
  18. package/dist/agent-docs/manifest.json +310 -36
  19. package/dist/components/design-tokens.js +138 -66
  20. package/dist/components/nav-tokens.js +41 -0
  21. package/dist/components/ui/app-bottom-nav.js +125 -130
  22. package/dist/components/ui/app-data-grid/app-data-grid.js +874 -0
  23. package/dist/components/ui/app-data-grid/engine/use-grid-column-resize.js +110 -0
  24. package/dist/components/ui/app-data-grid/engine/use-grid-engine.js +598 -0
  25. package/dist/components/ui/app-data-grid/engine/use-grid-infinite-loader.js +50 -0
  26. package/dist/components/ui/app-data-grid/engine/use-grid-virtualizer.js +90 -0
  27. package/dist/components/ui/app-data-grid/grid-aggregate.js +5 -0
  28. package/dist/components/ui/app-data-grid/grid-column-registry.js +28 -0
  29. package/dist/components/ui/app-data-grid/grid-columns.js +204 -0
  30. package/dist/components/ui/app-data-grid/grid-filter-compile.js +33 -0
  31. package/dist/components/ui/app-data-grid/grid-filter-operators.js +139 -0
  32. package/dist/components/ui/app-data-grid/grid-grouping.js +104 -0
  33. package/dist/components/ui/app-data-grid/grid-header-matrix.js +112 -0
  34. package/dist/components/ui/app-data-grid/grid-i18n.js +207 -0
  35. package/dist/components/ui/app-data-grid/grid-mount-count.js +8 -0
  36. package/dist/components/ui/app-data-grid/grid-reducer.js +200 -0
  37. package/dist/components/ui/app-data-grid/grid-result-scope.js +35 -0
  38. package/dist/components/ui/app-data-grid/grid-tokens.js +169 -0
  39. package/dist/components/ui/app-data-grid/grid-view-preset.js +97 -0
  40. package/dist/components/ui/app-data-grid/parts/grid-actions-row.js +86 -0
  41. package/dist/components/ui/app-data-grid/parts/grid-cell-text.js +67 -0
  42. package/dist/components/ui/app-data-grid/parts/grid-column-registry-panel.js +320 -0
  43. package/dist/components/ui/app-data-grid/parts/grid-density-control.js +88 -0
  44. package/dist/components/ui/app-data-grid/parts/grid-filter-chips.js +224 -0
  45. package/dist/components/ui/app-data-grid/parts/grid-filter-editor.js +197 -0
  46. package/dist/components/ui/app-data-grid/parts/grid-filter-panel.js +386 -0
  47. package/dist/components/ui/app-data-grid/parts/grid-filter-row.js +273 -0
  48. package/dist/components/ui/app-data-grid/parts/grid-fullscreen-toggle.js +29 -0
  49. package/dist/components/ui/app-data-grid/parts/grid-group-row.js +135 -0
  50. package/dist/components/ui/app-data-grid/parts/grid-header.js +338 -0
  51. package/dist/components/ui/app-data-grid/parts/grid-pagination-control.js +218 -0
  52. package/dist/components/ui/app-data-grid/parts/grid-row.js +181 -0
  53. package/dist/components/ui/app-data-grid/parts/grid-scroll-area.js +186 -0
  54. package/dist/components/ui/app-data-grid/parts/grid-selection-bar.js +195 -0
  55. package/dist/components/ui/app-data-grid/parts/grid-status-surface.js +66 -0
  56. package/dist/components/ui/app-data-grid/parts/grid-table.js +482 -0
  57. package/dist/components/ui/app-data-grid/parts/grid-toolbar-slots.js +192 -0
  58. package/dist/components/ui/app-data-grid/use-grid-filters.js +173 -0
  59. package/dist/components/ui/app-select.js +332 -222
  60. package/dist/components/ui/app-sidebar-mobile.js +119 -104
  61. package/dist/components/ui/app-sidebar.js +516 -313
  62. package/dist/components/ui/button.js +2 -1
  63. package/dist/components/ui/gantt/components/Chart/Chart.js +1 -1
  64. package/dist/components/ui/nav-badge.js +66 -0
  65. package/dist/components/ui/sidebar.js +272 -207
  66. package/dist/components/ui/tables/data-cross-table/data-cross-table.js +6 -6
  67. package/dist/components/ui/tables/data-table/data-table-constants.js +36 -16
  68. package/dist/components/ui/tables/data-table/data-table-i18n.js +135 -1
  69. package/dist/css-for-template.css +27 -0
  70. package/dist/index.d.ts +5872 -144
  71. package/dist/index.js +473 -406
  72. package/dist/node_modules/eventemitter3/index2.js +1 -1
  73. package/dist/styles.css +2 -1
  74. package/dist/styles.v3.css +1 -1
  75. package/package.json +25 -7
  76. /package/dist/agent-docs/components/{truncated-cell.md → TruncatedCell.md} +0 -0
@@ -8,18 +8,18 @@ Rich text editor powered by Lexical with optional Markdown sync. Supports config
8
8
 
9
9
  ## Props
10
10
 
11
- | Prop | Type | Default | Description |
12
- | ---------------- | ---------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ---------------------- |
13
- | `defaultValue` | `string` | `undefined` | Initial content. Interpreted as Markdown when `onlyMarkdown=true`, plain text otherwise. |
14
- | `onValueChange` | `(markdown: string, meta: { mentions: MentionItem[] }) => void` | `undefined` | Fires on every edit with the current Markdown and a metadata object. `meta.mentions` is the deduped (by `id`) list of mentions in the text (empty when mentions are disabled). Takes precedence over `onMarkdownEdit`. |
15
- | `onMarkdownEdit` | `(markdown: string) => void` | `undefined` | **Deprecated** — use `onValueChange`. Still honored as a fallback when `onValueChange` is not provided, but never receives mention metadata. |
16
- | `plugins` | `("clear" \| "counter")[]` | `[]` | Enable optional plugins: clear buttons, character counter. |
17
- | `toolbars` | `("block-format" \| "font-format" \| "history")[]` | `[]` | Enable toolbar groups. |
18
- | `placeholder` | `string` | `"Start typing..."` | Placeholder for empty editor. |
19
- | `onlyMarkdown` | `boolean` | `true` | Treat `defaultValue` as Markdown and sync editor to Markdown. If `false`, `defaultValue` is plain text. |
20
- | `className` | `string` | `"overflow-hidden rounded-lg border border-d-border"` | Extra classes for the content editable. |
21
- | `mentions` | `MentionItem[] \| (() => MentionItem[] \| Promise<MentionItem[]>)` | `undefined` | Enables @mention support when provided. Either a ready array (filtered client-side) or a **loader** called once on first menu open (no preload on mount). When omitted, no mention node/plugin/transformer is registered and output is identical to a mention-less editor. |
22
- | `mentionTrigger` | `string` | `"@"` | Single character that opens the mention typeahead menu. |
11
+ | Prop | Type | Default | Description |
12
+ | ---------------- | ------------------------------------------------------------------ | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
13
+ | `defaultValue` | `string` | `undefined` | Initial content. Interpreted as Markdown when `onlyMarkdown=true`, plain text otherwise. |
14
+ | `onValueChange` | `(markdown: string, meta: { mentions: MentionItem[] }) => void` | `undefined` | Fires on every edit with the current Markdown and a metadata object. `meta.mentions` is the deduped (by `id`) list of mentions in the text (empty when mentions are disabled). Takes precedence over `onMarkdownEdit`. |
15
+ | `onMarkdownEdit` | `(markdown: string) => void` | `undefined` | **Deprecated** — use `onValueChange`. Still honored as a fallback when `onValueChange` is not provided, but never receives mention metadata. |
16
+ | `plugins` | `("clear" \| "counter")[]` | `[]` | Enable optional plugins: clear buttons, character counter. |
17
+ | `toolbars` | `("block-format" \| "font-format" \| "history")[]` | `[]` | Enable toolbar groups. |
18
+ | `placeholder` | `string` | `"Start typing..."` | Placeholder for empty editor. |
19
+ | `onlyMarkdown` | `boolean` | `true` | Treat `defaultValue` as Markdown and sync editor to Markdown. If `false`, `defaultValue` is plain text. |
20
+ | `className` | `string` | `"overflow-hidden rounded-lg border border-d-border"` | Extra classes for the content editable. |
21
+ | `mentions` | `MentionItem[] \| (() => MentionItem[] \| Promise<MentionItem[]>)` | `undefined` | Enables @mention support when provided. Either a ready array (filtered client-side) or a **loader** called once on first menu open (no preload on mount). When omitted, no mention node/plugin/transformer is registered and output is identical to a mention-less editor. |
22
+ | `mentionTrigger` | `string` | `"@"` | Single character that opens the mention typeahead menu. |
23
23
 
24
24
  ### MentionItem
25
25
 
@@ -161,7 +161,12 @@ import { AppEditor, type MentionItem } from "laif-ds";
161
161
 
162
162
  const people: MentionItem[] = [
163
163
  { id: 1, label: "Alice Rossi", value: "alice@laif.it", sublabel: "Product" },
164
- { id: 2, label: "Bob Bianchi", value: "bob@laif.it", sublabel: "Engineering" },
164
+ {
165
+ id: 2,
166
+ label: "Bob Bianchi",
167
+ value: "bob@laif.it",
168
+ sublabel: "Engineering",
169
+ },
165
170
  ];
166
171
 
167
172
  export function EditorWithMentions() {
@@ -49,6 +49,8 @@ The component uses discriminated union types based on the `multiple` prop.
49
49
  | `onClear` | `() => void` | `undefined` | Callback fired when clear button is clicked |
50
50
  | `id` | `string` | `undefined` | HTML id attribute for the trigger (useful for testing) |
51
51
  | `data-testid` | `string` | `undefined` | Test identifier attribute for E2E testing (e.g. Playwright) |
52
+ | `aria-label` | `string` | `undefined` | Accessible name forwarded to the trigger. Applied ONLY when `label` is absent |
53
+ | `aria-labelledby` | `string` | `undefined` | Id(s) of external element(s) naming the trigger. Applied ONLY when `label` is absent |
52
54
 
53
55
  ### Single Select Props
54
56
 
@@ -498,6 +500,54 @@ export function CustomRenderSelect() {
498
500
 
499
501
  ---
500
502
 
503
+ ## Accessibility and layer behaviour
504
+
505
+ ### Accessible name
506
+
507
+ The trigger is a `role="combobox"`. How it is named depends on whether `label` is set:
508
+
509
+ - **with `label`**: `aria-labelledby` points at the label plus the current value (`"<labelId> <valueId>"`). A `aria-label` / `aria-labelledby` passed by the consumer is ignored in this branch on purpose — a second name next to a visible label is a WCAG 2.5.3 risk.
510
+ - **without `label`**: the trigger falls back to whatever the consumer passes — `aria-labelledby` first, then `aria-label` — and to NOTHING if neither is passed. It no longer falls back to the value id, which made the accessible name change every time the user picked an option (WCAG 4.1.2).
511
+
512
+ Story: `SenzaEtichettaNomeAccessibile`.
513
+
514
+ ### Keyboard
515
+
516
+ On the closed trigger: `Enter`, `Space`, `ArrowDown`, `ArrowUp`, `Home`, `End` open the list. With the list open: `ArrowDown` / `ArrowUp` / `Home` / `End` move the active option (disabled options are skipped), `Enter` commits the active option, `Space` closes, `Escape` dismisses, `Tab` moves to the next element in the document AND dismisses the list. `aria-activedescendant` tracks the active option while open; `aria-controls` points at the `[cmdk-list]` node that carries `role="listbox"`.
517
+
518
+ Stories: `AccessibilitaTastiera`, `TastieraElencoAperto`, `CongedoDaTastieraEClickFuori`.
519
+
520
+ ### The popover is NOT modal (behaviour change) — measured
521
+
522
+ The listbox is rendered inside a Radix `Popover` with `modal={false}`.
523
+
524
+ **Why.** With `modal`, Radix renders `PopoverContentModal`, which calls `hideOthers()` from `aria-hidden`. Measured: with the list open, the trigger ended up inside an `aria-hidden="true"` subtree while focus was still on it (`onOpenAutoFocus` is prevented for the mobile-keyboard reason documented below). So exactly while `aria-expanded="true"`, no screen reader could read the combobox, its state, or its `aria-controls`. A select-only combobox is not modal per APG.
525
+
526
+ **What else changed.** The modal branch carries four behaviours, and dropping it dropped all four: `hideOthers` (the one we wanted gone), `RemoveScroll`, `disableOutsidePointerEvents: true` and `trapFocus`. The table below is the measured delta — obtained by flipping `modal` in `app-select.tsx` and re-running the two stories in the browser test runner.
527
+
528
+ | Situation | with `modal` (before) | with `modal={false}` (now) |
529
+ | --- | --- | --- |
530
+ | Trigger inside an `aria-hidden` subtree while the list is open | yes | no |
531
+ | `AppSelect` nested in another `Popover`, ONE click on a target outside both | the select closes, the surrounding Popover stays open (`aria-expanded="true"`), the target's `onClick` does not fire (counter `0`) | both close (`"false"` / `"false"`) and the target's `onClick` fires (counter `1`) |
532
+ | What a real click at the outside target's centre hits (`document.elementFromPoint`) | the `HTML` element — the target's computed `pointer-events` is `none` | the target itself — computed `pointer-events` is `auto` |
533
+ | Page scroll with the list open | body carries `data-scroll-locked="1"`, computed body `overflow: hidden`, a `wheel` event is `defaultPrevented` | no lock attribute, `overflow: visible`, the `wheel` event is not prevented — the page scrolls under the open list |
534
+ | `Tab` from the open trigger | focus reaches the next element, but the list stays OPEN (the modal branch prevents `onFocusOutside`) | focus reaches the next element and the list dismisses |
535
+
536
+ Two notes on the measurement itself, so nobody re-derives them wrongly:
537
+
538
+ - assigning `scrollTop` from script is NOT a probe for the scroll lock: it moved the page in both branches (200 → 200). `RemoveScroll` cancels the scroll *event* and hides the scrollbar, it does not disable the API.
539
+ - `trapFocus` is inert in this component: `onOpenAutoFocus` is prevented, so focus never enters the portal and Radix's `FocusScope` has nothing to pull back. The `Tab` difference in the table comes from `onFocusOutside`, not from the focus trap.
540
+
541
+ Stories: `DentroUnPopoverAnnidato`, `PaginaScorreEFuocoNonIntrappolato`, `DentroUnDialogModale`.
542
+
543
+ ### Residual limits
544
+
545
+ - **A click outside now also activates what is under the pointer.** The modal branch gave a free "the first outside click only closes the menu" guard; it is gone. In a nested layout — an `AppSelect` inside another `Popover`, the shape used by the DataTable sorting panel — one click outside now dismisses BOTH layers and fires the underlying handler. If a consumer needs the old guard, it has to be added explicitly at that call site (e.g. `onInteractOutside` on the surrounding layer); `AppSelect` will not restore it, because bringing `modal` back would bring `hideOthers` back with it.
546
+ - **The page scrolls under the open list.** The list stays anchored to the trigger (Radix repositions it), but the content behind it moves.
547
+ - Inside a modal `Dialog` the non-modal popover still works: it opens after the dialog, so its dismissable layer sits higher in the stack and receives `pointer-events: auto` (measured by `DentroUnDialogModale`, which picks an option with the pointer).
548
+
549
+ ---
550
+
501
551
  ## Notes
502
552
 
503
553
  - **React 19 Compatible**: Properly handles JSX labels without ref warnings