laif-ds 1.0.5 → 1.1.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 (93) hide show
  1. package/dist/CHANGELOG.md +23 -0
  2. package/dist/_virtual/index2.js +2 -5
  3. package/dist/_virtual/index3.js +5 -2
  4. package/dist/_virtual/index4.js +5 -5
  5. package/dist/_virtual/index5.js +5 -5
  6. package/dist/_virtual/index6.js +2 -2
  7. package/dist/_virtual/index7.js +2 -2
  8. package/dist/agent-docs/adoption-report.json +165 -39
  9. package/dist/agent-docs/components/AppCard.md +25 -21
  10. package/dist/agent-docs/components/AppDataGrid/columns.md +113 -0
  11. package/dist/agent-docs/components/AppDataGrid/dom-hooks.md +75 -0
  12. package/dist/agent-docs/components/AppDataGrid/examples.md +129 -0
  13. package/dist/agent-docs/components/AppDataGrid/filtering.md +126 -0
  14. package/dist/agent-docs/components/AppDataGrid/grouping.md +20 -0
  15. package/dist/agent-docs/components/AppDataGrid/i18n-and-accessibility.md +40 -0
  16. package/dist/agent-docs/components/AppDataGrid/layout.md +45 -0
  17. package/dist/agent-docs/components/AppDataGrid/migration-from-datatable.md +32 -0
  18. package/dist/agent-docs/components/AppDataGrid/saved-views.md +76 -0
  19. package/dist/agent-docs/components/AppDataGrid/selection.md +44 -0
  20. package/dist/agent-docs/components/AppDataGrid/server-and-pagination.md +73 -0
  21. package/dist/agent-docs/components/AppDataGrid/toolbar.md +28 -0
  22. package/dist/agent-docs/components/AppDataGrid.md +278 -0
  23. package/dist/agent-docs/components/AppEditor.md +18 -13
  24. package/dist/agent-docs/components/AppSelect.md +51 -0
  25. package/dist/agent-docs/components/DataTable.md +40 -3
  26. package/dist/agent-docs/components/DatePicker.md +8 -7
  27. package/dist/agent-docs/components/DropdownMenu.md +2 -0
  28. package/dist/agent-docs/components/FileUploader.md +12 -12
  29. package/dist/agent-docs/components/GridFilterPanel.md +128 -0
  30. package/dist/agent-docs/components/SidebarMenuBadge.md +87 -0
  31. package/dist/agent-docs/components-list.md +16 -1
  32. package/dist/agent-docs/manifest.json +253 -30
  33. package/dist/components/design-tokens.js +138 -2
  34. package/dist/components/ui/app-data-grid/app-data-grid.js +900 -0
  35. package/dist/components/ui/app-data-grid/engine/use-grid-column-resize.js +110 -0
  36. package/dist/components/ui/app-data-grid/engine/use-grid-engine.js +621 -0
  37. package/dist/components/ui/app-data-grid/engine/use-grid-infinite-loader.js +50 -0
  38. package/dist/components/ui/app-data-grid/engine/use-grid-virtualizer.js +90 -0
  39. package/dist/components/ui/app-data-grid/grid-aggregate.js +5 -0
  40. package/dist/components/ui/app-data-grid/grid-column-registry.js +28 -0
  41. package/dist/components/ui/app-data-grid/grid-columns.js +204 -0
  42. package/dist/components/ui/app-data-grid/grid-filter-client.js +73 -0
  43. package/dist/components/ui/app-data-grid/grid-filter-compile.js +33 -0
  44. package/dist/components/ui/app-data-grid/grid-filter-operators.js +141 -0
  45. package/dist/components/ui/app-data-grid/grid-grouping.js +104 -0
  46. package/dist/components/ui/app-data-grid/grid-header-matrix.js +112 -0
  47. package/dist/components/ui/app-data-grid/grid-i18n.js +208 -0
  48. package/dist/components/ui/app-data-grid/grid-mount-count.js +8 -0
  49. package/dist/components/ui/app-data-grid/grid-reducer.js +202 -0
  50. package/dist/components/ui/app-data-grid/grid-result-scope.js +35 -0
  51. package/dist/components/ui/app-data-grid/grid-tokens.js +169 -0
  52. package/dist/components/ui/app-data-grid/grid-view-preset.js +97 -0
  53. package/dist/components/ui/app-data-grid/parts/grid-actions-row.js +86 -0
  54. package/dist/components/ui/app-data-grid/parts/grid-cell-text.js +67 -0
  55. package/dist/components/ui/app-data-grid/parts/grid-column-registry-panel.js +320 -0
  56. package/dist/components/ui/app-data-grid/parts/grid-density-control.js +88 -0
  57. package/dist/components/ui/app-data-grid/parts/grid-filter-chips.js +234 -0
  58. package/dist/components/ui/app-data-grid/parts/grid-filter-editor.js +201 -0
  59. package/dist/components/ui/app-data-grid/parts/grid-filter-panel.js +397 -0
  60. package/dist/components/ui/app-data-grid/parts/grid-filter-row.js +277 -0
  61. package/dist/components/ui/app-data-grid/parts/grid-fullscreen-toggle.js +28 -0
  62. package/dist/components/ui/app-data-grid/parts/grid-group-row.js +135 -0
  63. package/dist/components/ui/app-data-grid/parts/grid-header.js +337 -0
  64. package/dist/components/ui/app-data-grid/parts/grid-pagination-control.js +238 -0
  65. package/dist/components/ui/app-data-grid/parts/grid-portal-container.js +14 -0
  66. package/dist/components/ui/app-data-grid/parts/grid-row.js +181 -0
  67. package/dist/components/ui/app-data-grid/parts/grid-scroll-area.js +185 -0
  68. package/dist/components/ui/app-data-grid/parts/grid-selection-bar.js +195 -0
  69. package/dist/components/ui/app-data-grid/parts/grid-status-surface.js +66 -0
  70. package/dist/components/ui/app-data-grid/parts/grid-table.js +482 -0
  71. package/dist/components/ui/app-data-grid/parts/grid-toolbar-slots.js +224 -0
  72. package/dist/components/ui/app-data-grid/use-grid-filters.js +183 -0
  73. package/dist/components/ui/app-select.js +334 -222
  74. package/dist/components/ui/button.js +7 -6
  75. package/dist/components/ui/date-picker.js +36 -34
  76. package/dist/components/ui/dropdown-menu.js +3 -3
  77. package/dist/components/ui/tables/data-cross-table/data-cross-table.js +6 -6
  78. package/dist/components/ui/tables/data-table/data-table-constants.js +36 -16
  79. package/dist/components/ui/tables/data-table/data-table-i18n.js +135 -1
  80. package/dist/css-for-template.css +26 -0
  81. package/dist/index.d.ts +5957 -124
  82. package/dist/index.js +462 -395
  83. package/dist/node_modules/eventemitter3/index.js +1 -1
  84. package/dist/node_modules/eventemitter3/index2.js +1 -1
  85. package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +1 -1
  86. package/dist/node_modules/recharts/es6/util/Events.js +1 -1
  87. package/dist/node_modules/style-to-object/cjs/index.js +1 -1
  88. package/dist/node_modules/unified/lib/index.js +1 -1
  89. package/dist/node_modules/use-sync-external-store/shim/index.js +1 -1
  90. package/dist/styles.css +2 -1
  91. package/dist/styles.v3.css +1 -1
  92. package/package.json +13 -6
  93. /package/dist/agent-docs/components/{truncated-cell.md → TruncatedCell.md} +0 -0
package/dist/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable technical changes to the laif-ds core will be documented in this fil
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [laif-ds@1.1.0]
9
+
10
+ ### 🚀 Added
11
+
12
+ - **AppDataGrid**: New data grid, the successor to `DataTable`. Columns are declared with the `createGrid*Column` builders (string, number, boolean, date, date-time, single/multi select, computed, display, action, row menu, column groups). Filters live in a filter row inside the columns by default (`filterMode="row"`) or in a panel (`filterMode="panel"`, work in progress), can be lifted outside the grid (`filters`, `GridFilterChips`, `useGridFilters`), and application-declared filter controls are supported (`filterControls`); a `toolbar.resetFilters` slot restores filters and search to the page's own defaults. Server mode via `onQueryChange`, fired only on search/sort/filter/page changes and debounced by `debounceTime`; `paginated` mode — with an AppSelect page-size picker, a "Page i/N" indicator — or an `infinite` source; `groupBy` grouping with aggregated cells; row selection with a page-selection bar for bulk actions; column pinning, resizing and reordering, notified through `onColumnWidthsChange` / `onColumnOrderChange` and capturable in saved views; `virtualized` rendering; `density` and full screen, with ghost toolbar buttons for the filter row, column visibility and full screen shown by default and individually disableable; saved views capturing filters, search, sorting, density, column visibility, widths and order (`preset`, `readGridViewPreset`, `createInMemoryGridViewStore`); `i18n` (`defaultGridI18n`); loading, empty and error/retry states; a polite live region announcing result changes. See `AppDataGrid.md`
13
+ - **DataTable**: The filter-option getters (`getStringFilterOptions`, `getNumberFilterOptions`, …), `defaultDataTableI18n` / `italianDataTableI18n` and the service helpers (`applyClientSideFilter`, `buildSearchFilter`, …) are now exported from the package root
14
+ - **designTokens**: The shared design-token object is now exported from the package root, including the new `table` (row/header heights, cell padding) and `tableZ` (z-index layers) entries
15
+ - **Button**: New `icon-xs` size
16
+ - **DatePicker** / **AppSelect**: New `portalContainer` prop to portal the popover into a given element instead of `<body>`, for use inside containers with their own stacking context (e.g. a full-screen grid)
17
+ - **DropdownMenu**: `DropdownMenuContent` accepts a `container` prop with the same purpose
18
+ - **AppSelect**: New `aria-label` and `aria-labelledby` props, used to name the trigger when no `label` is passed
19
+
20
+ ### 🔧 Changed
21
+
22
+ - **AppSelect**: The trigger is now an ARIA `combobox` (`aria-haspopup="listbox"`, `aria-controls`, `aria-activedescendant`): it opens with Enter, Space or the arrow keys, Arrow/Home/End move through the enabled options, and without `label`/`aria-label` its accessible name falls back to `placeholder`. The popover is no longer modal, so the rest of the page is not hidden from assistive technology while it is open. In multiple mode each chosen option exposes `aria-checked`, and search matches both the option label and its value
23
+ - **Theme**: In the default light theme `--colors--surface--secondary` (behind `d-secondary` and `d-muted`) now uses a new `neutral--150` step instead of `neutral--125`, so it is distinguishable from the page background
24
+ - **DataTable**: Deprecated in favour of **AppDataGrid**. It is still exported and existing code keeps compiling (no `@deprecated` tag, so consumer lint rules are not tripped); its docs and stories are marked deprecated. Migration guide: `AppDataGrid.md`
25
+ - **GridFilterPanel**: Exported for the lifted-filters panel layout but deprecated in favour of the AppDataGrid filter row (`filterMode="row"`)
26
+
27
+ ### 🐛 Fixed
28
+
29
+ - **AppSelect**: Options sharing the same label are no longer highlighted together, since each option is now keyed by its value instead of its label
30
+
8
31
  ## [laif-ds@1.0.5]
9
32
 
10
33
  ### 🚀 Added
@@ -1,8 +1,5 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
- import { __require as t } from "../node_modules/eventemitter3/index2.js";
4
- var r = t();
5
- const m = /* @__PURE__ */ e(r);
2
+ var e = { exports: {} };
6
3
  export {
7
- m as default
4
+ e as __module
8
5
  };
@@ -1,5 +1,8 @@
1
1
  "use client";
2
- var e = { exports: {} };
2
+ import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
+ import { __require as t } from "../node_modules/eventemitter3/index2.js";
4
+ var r = t();
5
+ const m = /* @__PURE__ */ e(r);
3
6
  export {
4
- e as __module
7
+ m as default
5
8
  };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
- import { __require as r } from "../node_modules/extend/index.js";
4
- var t = r();
5
- const x = /* @__PURE__ */ e(t);
2
+ import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.js";
3
+ import { __require as e } from "../node_modules/style-to-js/cjs/index.js";
4
+ var t = e();
5
+ const a = /* @__PURE__ */ r(t);
6
6
  export {
7
- x as default
7
+ a as default
8
8
  };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.js";
3
- import { __require as e } from "../node_modules/style-to-js/cjs/index.js";
4
- var t = e();
5
- const a = /* @__PURE__ */ r(t);
2
+ import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
+ import { __require as r } from "../node_modules/extend/index.js";
4
+ var t = r();
5
+ const x = /* @__PURE__ */ e(t);
6
6
  export {
7
- a as default
7
+ x as default
8
8
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- var e = { exports: {} };
2
+ var e = {};
3
3
  export {
4
- e as __module
4
+ e as __exports
5
5
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- var e = {};
2
+ var e = { exports: {} };
3
3
  export {
4
- e as __exports
4
+ e as __module
5
5
  };
@@ -1,23 +1,137 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-23T17:05:08.621Z",
3
+ "generatedAt": "2026-09-30T14:40:24.024Z",
4
4
  "package": {
5
5
  "name": "laif-ds",
6
- "version": "1.0.5"
6
+ "version": "1.1.0"
7
7
  },
8
8
  "summary": {
9
- "scannedFiles": 404,
10
- "deprecatedComponentsCount": 2,
11
- "deprecatedComponentsUsedCount": 0,
9
+ "scannedFiles": 502,
10
+ "deprecatedComponentsCount": 5,
11
+ "deprecatedComponentsUsedCount": 3,
12
12
  "componentsWithoutExamplesCount": 5,
13
13
  "componentsWithoutPropsTableCount": 30,
14
14
  "repeatedClassPatternsCount": 25,
15
- "lowAiReadinessComponentsCount": 41,
15
+ "lowAiReadinessComponentsCount": 42,
16
16
  "componentsWithoutAccessibilityCoverageCount": 44,
17
- "componentsWithWeakStateCoverageCount": 71,
18
- "averageAiReadinessScore": 56.33
17
+ "componentsWithWeakStateCoverageCount": 72,
18
+ "averageAiReadinessScore": 57.06
19
19
  },
20
- "deprecatedUsage": [],
20
+ "deprecatedUsage": [
21
+ {
22
+ "component": "DataTable",
23
+ "replacement": "AppDataGrid",
24
+ "totalOccurrences": 24,
25
+ "usages": [
26
+ {
27
+ "file": "src/components/ui/app-data-grid/parts/grid-filter-editor.tsx",
28
+ "occurrences": 3
29
+ },
30
+ {
31
+ "file": "src/components/design-tokens.ts",
32
+ "occurrences": 2
33
+ },
34
+ {
35
+ "file": "src/components/ui/app-data-grid/app-data-grid.tsx",
36
+ "occurrences": 2
37
+ },
38
+ {
39
+ "file": "src/components/ui/app-data-grid/app-data-grid.types.ts",
40
+ "occurrences": 2
41
+ },
42
+ {
43
+ "file": "src/components/ui/app-data-grid/grid-filter-operators.ts",
44
+ "occurrences": 2
45
+ },
46
+ {
47
+ "file": "src/components/ui/app-data-grid/parts/grid-scroll-area.tsx",
48
+ "occurrences": 2
49
+ },
50
+ {
51
+ "file": "src/components/ui/tables/data-table/data-table.tsx",
52
+ "occurrences": 2
53
+ },
54
+ {
55
+ "file": "src/components/ui/app-data-grid/grid-i18n.ts",
56
+ "occurrences": 1
57
+ },
58
+ {
59
+ "file": "src/components/ui/app-data-grid/parts/grid-cell-text.tsx",
60
+ "occurrences": 1
61
+ },
62
+ {
63
+ "file": "src/components/ui/app-data-grid/parts/grid-column-registry-panel.tsx",
64
+ "occurrences": 1
65
+ },
66
+ {
67
+ "file": "src/components/ui/app-data-grid/parts/grid-filter-panel.tsx",
68
+ "occurrences": 1
69
+ },
70
+ {
71
+ "file": "src/components/ui/app-data-grid/parts/grid-filter-row.tsx",
72
+ "occurrences": 1
73
+ },
74
+ {
75
+ "file": "src/components/ui/app-data-grid/parts/grid-group-row.tsx",
76
+ "occurrences": 1
77
+ },
78
+ {
79
+ "file": "src/components/ui/app-data-grid/parts/grid-selection-bar.tsx",
80
+ "occurrences": 1
81
+ },
82
+ {
83
+ "file": "src/components/ui/app-select.tsx",
84
+ "occurrences": 1
85
+ },
86
+ {
87
+ "file": "src/components/ui/tables/data-table/data-table.utils.ts",
88
+ "occurrences": 1
89
+ }
90
+ ]
91
+ },
92
+ {
93
+ "component": "GridFilterPanel",
94
+ "replacement": "AppDataGrid",
95
+ "totalOccurrences": 7,
96
+ "usages": [
97
+ {
98
+ "file": "src/components/ui/app-data-grid/app-data-grid.types.ts",
99
+ "occurrences": 2
100
+ },
101
+ {
102
+ "file": "src/components/ui/app-data-grid/app-data-grid.tsx",
103
+ "occurrences": 1
104
+ },
105
+ {
106
+ "file": "src/components/ui/app-data-grid/index.ts",
107
+ "occurrences": 1
108
+ },
109
+ {
110
+ "file": "src/components/ui/app-data-grid/parts/grid-filter-panel.tsx",
111
+ "occurrences": 1
112
+ },
113
+ {
114
+ "file": "src/components/ui/app-data-grid/parts/grid-filter-row.tsx",
115
+ "occurrences": 1
116
+ },
117
+ {
118
+ "file": "src/components/ui/app-data-grid/use-grid-filters.ts",
119
+ "occurrences": 1
120
+ }
121
+ ]
122
+ },
123
+ {
124
+ "component": "SidebarMenuBadge",
125
+ "replacement": "NavItem.badge",
126
+ "totalOccurrences": 4,
127
+ "usages": [
128
+ {
129
+ "file": "src/components/ui/sidebar.tsx",
130
+ "occurrences": 4
131
+ }
132
+ ]
133
+ }
134
+ ],
21
135
  "documentationGaps": {
22
136
  "componentsWithoutExamples": [
23
137
  "AppMultipleSelectDropdown",
@@ -160,6 +274,7 @@
160
274
  "Sheet",
161
275
  "ShikiHighlighter",
162
276
  "Sidebar",
277
+ "SidebarMenuBadge",
163
278
  "Skeleton",
164
279
  "Slider",
165
280
  "Sonner",
@@ -312,6 +427,10 @@
312
427
  "name": "SecurePdfViewer",
313
428
  "score": 40
314
429
  },
430
+ {
431
+ "name": "SidebarMenuBadge",
432
+ "score": 40
433
+ },
315
434
  {
316
435
  "name": "Toggle",
317
436
  "score": 40
@@ -350,9 +469,10 @@
350
469
  "repeatedClassNames": [
351
470
  {
352
471
  "className": "flex items-center gap-2",
353
- "occurrences": 36,
472
+ "occurrences": 39,
354
473
  "files": [
355
474
  "src/components/stories/app-checkbox.stories.tsx",
475
+ "src/components/stories/app-data-grid-completa.stories.tsx",
356
476
  "src/components/stories/app-dialog.stories.tsx",
357
477
  "src/components/stories/app-radio-group.stories.tsx",
358
478
  "src/components/stories/app-select.stories.tsx",
@@ -459,6 +579,22 @@
459
579
  "src/components/stories/tabs.stories.tsx"
460
580
  ]
461
581
  },
582
+ {
583
+ "className": "text-d-muted-foreground",
584
+ "occurrences": 12,
585
+ "files": [
586
+ "src/components/stories/app-data-grid-completa.stories.tsx",
587
+ "src/components/stories/app-data-grid-preset.stories.tsx",
588
+ "src/components/stories/app-dialog.stories.tsx",
589
+ "src/components/stories/app-time-picker.stories.tsx",
590
+ "src/components/ui/app-data-grid/parts/grid-toolbar-slots.tsx",
591
+ "src/components/ui/app-form.tsx",
592
+ "src/components/ui/app-multiple-select-dropdown.tsx",
593
+ "src/components/ui/app-select.tsx",
594
+ "src/components/ui/date-picker.tsx",
595
+ "src/components/ui/weekly-calendar/calendar-header.tsx"
596
+ ]
597
+ },
462
598
  {
463
599
  "className": "flex h-full overflow-hidden",
464
600
  "occurrences": 12,
@@ -524,16 +660,16 @@
524
660
  ]
525
661
  },
526
662
  {
527
- "className": "text-d-muted-foreground",
663
+ "className": "text-d-muted-foreground text-xs",
528
664
  "occurrences": 7,
529
665
  "files": [
530
- "src/components/stories/app-dialog.stories.tsx",
531
- "src/components/stories/app-time-picker.stories.tsx",
532
- "src/components/ui/app-form.tsx",
533
- "src/components/ui/app-multiple-select-dropdown.tsx",
534
- "src/components/ui/app-select.tsx",
535
- "src/components/ui/date-picker.tsx",
536
- "src/components/ui/weekly-calendar/calendar-header.tsx"
666
+ "src/components/editor/plugins/mention-plugin.tsx",
667
+ "src/components/stories/app-card.stories.tsx",
668
+ "src/components/stories/input.stories.tsx",
669
+ "src/components/ui/app-data-grid/parts/grid-filter-editor.tsx",
670
+ "src/components/ui/tables/data-cross-table/cell-editor-dialog.tsx",
671
+ "src/components/ui/tables/data-cross-table/data-cross-table.tsx",
672
+ "src/components/ui/tables/data-cross-table/editable-input.tsx"
537
673
  ]
538
674
  },
539
675
  {
@@ -566,18 +702,6 @@
566
702
  "src/components/stories/spinner.stories.tsx"
567
703
  ]
568
704
  },
569
- {
570
- "className": "text-d-muted-foreground text-xs",
571
- "occurrences": 6,
572
- "files": [
573
- "src/components/editor/plugins/mention-plugin.tsx",
574
- "src/components/stories/app-card.stories.tsx",
575
- "src/components/stories/input.stories.tsx",
576
- "src/components/ui/tables/data-cross-table/cell-editor-dialog.tsx",
577
- "src/components/ui/tables/data-cross-table/data-cross-table.tsx",
578
- "src/components/ui/tables/data-cross-table/editable-input.tsx"
579
- ]
580
- },
581
705
  {
582
706
  "className": "flex items-center gap-1 font-normal",
583
707
  "occurrences": 6,
@@ -590,6 +714,17 @@
590
714
  "src/components/editor/plugins/toolbar/block-format/format-quote.tsx"
591
715
  ]
592
716
  },
717
+ {
718
+ "className": "flex items-center gap-1",
719
+ "occurrences": 6,
720
+ "files": [
721
+ "src/components/editor/plugins/toolbar/history-toolbar-plugin.tsx",
722
+ "src/components/stories/app-select.stories.tsx",
723
+ "src/components/ui/app-data-grid/parts/grid-group-row.tsx",
724
+ "src/components/ui/app-kanban.tsx",
725
+ "src/components/ui/calendar.tsx"
726
+ ]
727
+ },
593
728
  {
594
729
  "className": "text-sm font-semibold",
595
730
  "occurrences": 6,
@@ -600,15 +735,6 @@
600
735
  "src/components/stories/truncated-cell.stories.tsx",
601
736
  "src/components/ui/weekly-calendar/appointment-card.tsx"
602
737
  ]
603
- },
604
- {
605
- "className": "text-lg font-semibold",
606
- "occurrences": 6,
607
- "files": [
608
- "src/components/stories/app-kanban.stories.tsx",
609
- "src/components/stories/changelog.stories.tsx",
610
- "src/components/stories/playground.stories.tsx"
611
- ]
612
738
  }
613
739
  ]
614
740
  }
@@ -10,24 +10,24 @@ Enhanced card component built on top of the base Card component. Provides a simp
10
10
 
11
11
  ### AppCardProps
12
12
 
13
- | Prop | Type | Default | Description |
14
- | ------------------ | ------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------- |
15
- | `title` | `string \| React.ReactNode` | `undefined` | Card title displayed in the header. |
16
- | `description` | `string \| React.ReactNode` | `undefined` | Card description displayed below the title. |
17
- | `header` | `React.ReactNode` | `undefined` | Custom header content; overrides `title` and `description`. |
18
- | `body` | `React.ReactNode` | `undefined` | Main content rendered inside CardContent. |
19
- | `children` | `React.ReactNode` | `undefined` | Fallback body content when `body` is not provided. |
20
- | `actions` | `React.ReactNode` | `undefined` | Right-aligned action elements inside the header. |
21
- | `footer` | `React.ReactNode` | `undefined` | Footer content (typically action buttons). |
22
- | `variant` | `AppCardVariant` | `"default"` | Visual variant of the card (see table below). |
23
- | `size` | `"sm" \| "default" \| "lg" \| "none"` | `undefined` | Controls internal padding via the base Card component. |
24
- | `isLoading` | `boolean` | `false` | When true, renders skeleton placeholders instead of content. |
25
- | `showHeaderBorder` | `boolean` | `false` | Displays a border between the header and body sections. |
26
- | `showFooterBorder` | `boolean` | `false` | Displays a border between the body and footer sections. |
27
- | `className` | `string` | `undefined` | Additional classes for the card container. |
28
- | `headerClassName` | `string` | `undefined` | Additional classes for the header section. |
29
- | `bodyClassName` | `string` | `undefined` | Additional classes for the body section. |
30
- | `footerClassName` | `string` | `undefined` | Additional classes for the footer section. |
13
+ | Prop | Type | Default | Description |
14
+ | ------------------ | ------------------------------------- | ----------- | ------------------------------------------------------------ |
15
+ | `title` | `string \| React.ReactNode` | `undefined` | Card title displayed in the header. |
16
+ | `description` | `string \| React.ReactNode` | `undefined` | Card description displayed below the title. |
17
+ | `header` | `React.ReactNode` | `undefined` | Custom header content; overrides `title` and `description`. |
18
+ | `body` | `React.ReactNode` | `undefined` | Main content rendered inside CardContent. |
19
+ | `children` | `React.ReactNode` | `undefined` | Fallback body content when `body` is not provided. |
20
+ | `actions` | `React.ReactNode` | `undefined` | Right-aligned action elements inside the header. |
21
+ | `footer` | `React.ReactNode` | `undefined` | Footer content (typically action buttons). |
22
+ | `variant` | `AppCardVariant` | `"default"` | Visual variant of the card (see table below). |
23
+ | `size` | `"sm" \| "default" \| "lg" \| "none"` | `undefined` | Controls internal padding via the base Card component. |
24
+ | `isLoading` | `boolean` | `false` | When true, renders skeleton placeholders instead of content. |
25
+ | `showHeaderBorder` | `boolean` | `false` | Displays a border between the header and body sections. |
26
+ | `showFooterBorder` | `boolean` | `false` | Displays a border between the body and footer sections. |
27
+ | `className` | `string` | `undefined` | Additional classes for the card container. |
28
+ | `headerClassName` | `string` | `undefined` | Additional classes for the header section. |
29
+ | `bodyClassName` | `string` | `undefined` | Additional classes for the body section. |
30
+ | `footerClassName` | `string` | `undefined` | Additional classes for the footer section. |
31
31
 
32
32
  ### Variant Reference
33
33
 
@@ -203,13 +203,17 @@ export function NestedCards() {
203
203
  <div className="flex flex-col gap-3">
204
204
  <AppCard
205
205
  title="Nested Item A"
206
- body={<p className="text-sm">Flat cards have no border or shadow.</p>}
206
+ body={
207
+ <p className="text-sm">Flat cards have no border or shadow.</p>
208
+ }
207
209
  variant="flat"
208
210
  size="sm"
209
211
  />
210
212
  <AppCard
211
213
  title="Nested Item B"
212
- body={<p className="text-sm">Good for secondary content regions.</p>}
214
+ body={
215
+ <p className="text-sm">Good for secondary content regions.</p>
216
+ }
213
217
  variant="flat"
214
218
  size="sm"
215
219
  />
@@ -228,7 +232,7 @@ import { AppCard } from "laif-ds";
228
232
 
229
233
  export function SizeVariants() {
230
234
  return (
231
- <div className="flex flex-col gap-6 w-[400px]">
235
+ <div className="flex w-[400px] flex-col gap-6">
232
236
  <AppCard
233
237
  size="sm"
234
238
  title="Size: Small"
@@ -0,0 +1,113 @@
1
+ # AppDataGrid — Columns
2
+
3
+ > Part of the [AppDataGrid](../AppDataGrid.md) docs. The Props table and the `onQueryChange` payload are in the main file.
4
+
5
+ ## Column definition
6
+
7
+ ### Builders
8
+
9
+ | Builder | Column type | `cell` signature | `cell` required | `id` required | Sortable / filterable / searchable by default |
10
+ | ------------------------------ | -------------------- | ------------------------ | --------------- | ------------- | --------------------------------------------- |
11
+ | `createGridStringColumn` | `string` | `(value, row, tableRow)` | no | no | yes / yes / no |
12
+ | `createGridNumberColumn` | `number` | `(value, row, tableRow)` | no | no | yes / yes / no |
13
+ | `createGridBooleanColumn` | `boolean` | `(value, row, tableRow)` | no | no | yes / yes / no |
14
+ | `createGridDateColumn` | `date` | `(value, row, tableRow)` | no | no | yes / yes / no |
15
+ | `createGridDateTimeColumn` | `datetime` | `(value, row, tableRow)` | no | no | yes / yes / no |
16
+ | `createGridSingleSelectColumn` | `list_single_select` | `(value, row, tableRow)` | no | no | yes / yes / no |
17
+ | `createGridMultiSelectColumn` | `list_multi_select` | `(value, row, tableRow)` | no | no | yes / yes / no |
18
+ | `createGridComputedColumn` | `other` | `(value, row, tableRow)` | no | no | no / no / no |
19
+ | `createGridActionColumn` | — | `(row)` | **yes** | **yes** | never |
20
+ | `createGridDisplayColumn` | — | `(row)` | **yes** | no | no / no / opt-in |
21
+ | `createGridRowMenuColumn` | — | none (`rowMenu`) | n/a | **yes** | never |
22
+ | `createGridColumnGroup` | group | — | — | **yes** | — |
23
+
24
+ The two `cell` arities are copied from `DataTable` on purpose, so existing `cell:` closures keep compiling
25
+ after a rename. All builders are generic: `createGridNumberColumn<Row, number>({ ... })`.
26
+
27
+ Column ids: explicit `id`, else `accessorKey`, else derived from `headerLabel` (`<type>-<slug>`); a
28
+ column with none of them throws. Ids must be stable across reloads — they key widths, visibility, order,
29
+ sorting and saved views.
30
+
31
+ ### Accessor builder options
32
+
33
+ Applies to the eight accessor builders (`accessorKey`-based).
34
+
35
+ | Option | Type | Default | Description |
36
+ | ----------------- | -------------------------------------------------------------------------------- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
37
+ | `accessorKey` | `string` | — | **Required.** Field to read; dotted paths (`user.name`) read nested values. Also the key used in `computedFilter`. |
38
+ | `header` | `string \| ReactNode` | — | **Required.** When not a string, `headerLabel` is required by the type. |
39
+ | `headerLabel` | `string` | `header` if a non-empty string, else `id` | Text form of the header: accessible name, menus, chips, columns panel. |
40
+ | `id` | `string` | `accessorKey` | Stable column id. |
41
+ | `sortable` | `boolean` | `true` (`false` for computed) | Renders the sort button. Note: `DataTable` defaulted to `false`. |
42
+ | `filterable` | `boolean` | `true` (`false` for computed) | Offers the column in the filter row / panel. Note: `DataTable` defaulted to `false`. |
43
+ | `searchable` | `boolean` | `false` | **Opt-in.** Includes the column in the global search (client matching and `computedFilter`). Enable it only on text-like columns the backend can search. |
44
+ | `filterType` | `GridFilterType` (column types except `"other"`) | the column type | How the column is filtered, when different from its type (e.g. `"list_single_select"` + `options` on a string column). |
45
+ | `options` | `readonly string[] \| readonly GridSelectOption[] \| readonly AppSelectOption[]` | `undefined` | Choices of a list column (or of a list `filterType`). Bare strings are normalised to `{ value, label }`. Numeric `value`s are kept as numbers in the payload. |
46
+ | `pinned` | `"left" \| "right"` | `undefined` | Sticks the column to an edge during horizontal scroll. Pin a **prefix** (left) or a **suffix** (right): offsets accumulate in declaration order. |
47
+ | `align` | `"left" \| "right"` | `"left"` | Content alignment of header, cells, group cells and footer. `"right"` adds `tabular-nums`. |
48
+ | `width` | `number` | `160` (elastic) | Initial width in px (64–1200). Columns without a declared width share leftover space; a drag replaces it. |
49
+ | `rowHeader` | `boolean` | `false` | Renders this column's cells as `<th scope="row">` — the row's name for assistive tech and for row-menu labels. At most one column per grid (a second one throws). |
50
+ | `cell` | `(value, row, tableRow) => ReactNode` | stringified value | Cell renderer. Text returned as a string gets automatic truncation handling (tooltip + focusable target only when it overflows). |
51
+ | `cellClassName` | `string \| ((value, row) => string)` | `undefined` | Cell classes. Note the two-parameter callback. |
52
+ | `headerClassName` | `string` | `undefined` | Header cell classes. |
53
+ | `aggregatedCell` | `(rows: TData[]) => ReactNode` | `undefined` | Content of this column's cell in **group rows**. Receives every original row under the group, at any depth. Absent = empty group cell. |
54
+ | `aggregate` | `(rows: TData[]) => ReactNode` | `undefined` | Column total in the sticky `<tfoot>`, over the rows after search/filters/sort (the page when `paginated`). No footer unless a visible column declares one. |
55
+
56
+ Action / display / row-menu columns accept `id`, `header`/`headerLabel`, `pinned`, `width`, `align`,
57
+ `rowHeader` (display: also `searchable`). `createGridRowMenuColumn` takes `rowMenu` instead of `cell`.
58
+
59
+ ### Column groups (multi-level headers)
60
+
61
+ ```tsx
62
+ createGridColumnGroup<Row>({
63
+ id: "customer", // required, unique among ALL nodes (groups and leaves)
64
+ header: "Customer",
65
+ headerLabel: "Customer", // required when header is not a string
66
+ columns: [nameColumn, cityColumn /* or nested groups */],
67
+ });
68
+ ```
69
+
70
+ Groups add header rows only; rows, sorting, filtering, widths and pinning see the flat list of leaves.
71
+ Nesting depth is unlimited. Each body cell is linked to its headers through `id`/`headers`. A group whose
72
+ leaves are all hidden disappears.
73
+
74
+ ### Row menu column
75
+
76
+ ```tsx
77
+ createGridRowMenuColumn<Job>({
78
+ id: "actions",
79
+ header: "Actions",
80
+ pinned: "right",
81
+ width: 100,
82
+ rowMenu: (row) => [
83
+ { id: "open", label: "Open", onSelect: () => open(row.id) },
84
+ {
85
+ id: "duplicate",
86
+ label: "Duplicate",
87
+ onSelect: () => duplicate(row.id),
88
+ disabled: row.closed,
89
+ },
90
+ {
91
+ id: "delete",
92
+ label: "Delete",
93
+ destructive: true,
94
+ onSelect: () => remove(row.id),
95
+ },
96
+ ],
97
+ });
98
+ ```
99
+
100
+ Items are data (`GridRowMenuItem`: `id`, `label`, `onSelect`, `destructive?`, `disabled?`); the grid
101
+ renders the `…` trigger and a non-modal menu aligned to the end. The trigger's accessible name is
102
+ `i18n.table.rowMenu` plus the row's identity (from the `rowHeader` column, else the row id). Returning an
103
+ empty list (or `undefined`) renders no trigger.
104
+
105
+ ### Column helpers
106
+
107
+ - `createGridSorting([{ column: "name", order: "asc" }])` → `GridSorting` (`{ sort_by, sort_order }`).
108
+ - `createGridInitialState({ filters?, searchbarFilter?, sorting?, pagination?, columnVisibility? })` →
109
+ `GridInitialState` (for `initialState`).
110
+ - `toGridFilterColumns(columns)` → `GridFilterColumn[]` for `useGridFilters` (flat leaf columns; columns
111
+ without `accessorKey` are skipped).
112
+
113
+ ---