@crisp-ui-kit/crisp 0.34.0 → 0.36.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 (59) hide show
  1. package/dist/bulkbar.css +3 -0
  2. package/dist/bulkbar.layered.css +3 -0
  3. package/dist/cjs/components/bulkbar/bulkbar.js +1 -1
  4. package/dist/cjs/components/bulkbar/bulkbar.recipe.js +6 -0
  5. package/dist/cjs/components/datatable/datatable.js +65 -5
  6. package/dist/cjs/components/datatable/datatable.recipe.js +2 -0
  7. package/dist/cjs/components/filldoc/filldoc.js +102 -0
  8. package/dist/cjs/components/filldoc/filldoc.recipe.js +211 -0
  9. package/dist/cjs/components/filldoc/index.js +10 -0
  10. package/dist/cjs/components/filldoc/serialize.js +39 -0
  11. package/dist/cjs/components/fillsheet/fillsheet.js +719 -0
  12. package/dist/cjs/components/fillsheet/fillsheet.recipe.js +325 -0
  13. package/dist/cjs/components/fillsheet/index.js +12 -0
  14. package/dist/cjs/components/fillsheet/serialize.js +82 -0
  15. package/dist/cjs/index.js +2 -0
  16. package/dist/cjs/product/recordpanel/recordpanel.js +4 -2
  17. package/dist/cjs/product/recordpanel/recordpanel.recipe.js +8 -0
  18. package/dist/cjs/product/sidebar/sidebar.js +16 -3
  19. package/dist/datatable.css +13 -5
  20. package/dist/datatable.layered.css +13 -5
  21. package/dist/esm/components/bulkbar/bulkbar.js +1 -1
  22. package/dist/esm/components/bulkbar/bulkbar.recipe.js +6 -0
  23. package/dist/esm/components/datatable/datatable.js +65 -5
  24. package/dist/esm/components/datatable/datatable.recipe.js +2 -0
  25. package/dist/esm/components/filldoc/filldoc.js +66 -0
  26. package/dist/esm/components/filldoc/filldoc.recipe.js +208 -0
  27. package/dist/esm/components/filldoc/index.js +3 -0
  28. package/dist/esm/components/filldoc/serialize.js +35 -0
  29. package/dist/esm/components/fillsheet/fillsheet.js +683 -0
  30. package/dist/esm/components/fillsheet/fillsheet.recipe.js +322 -0
  31. package/dist/esm/components/fillsheet/index.js +3 -0
  32. package/dist/esm/components/fillsheet/serialize.js +76 -0
  33. package/dist/esm/index.js +2 -0
  34. package/dist/esm/product/recordpanel/recordpanel.js +4 -2
  35. package/dist/esm/product/recordpanel/recordpanel.recipe.js +8 -0
  36. package/dist/esm/product/sidebar/sidebar.js +17 -4
  37. package/dist/filldoc.css +31 -0
  38. package/dist/filldoc.d.ts +7 -0
  39. package/dist/filldoc.layered.css +33 -0
  40. package/dist/fillsheet.css +29 -0
  41. package/dist/fillsheet.d.ts +7 -0
  42. package/dist/fillsheet.layered.css +31 -0
  43. package/dist/recordpanel.css +6 -0
  44. package/dist/recordpanel.layered.css +6 -0
  45. package/dist/styles.css +84 -5
  46. package/dist/styles.layered.css +84 -5
  47. package/dist/types/components/datatable/datatable.d.ts +7 -1
  48. package/dist/types/components/filldoc/filldoc.d.ts +79 -0
  49. package/dist/types/components/filldoc/filldoc.recipe.d.ts +201 -0
  50. package/dist/types/components/filldoc/index.d.ts +3 -0
  51. package/dist/types/components/filldoc/serialize.d.ts +5 -0
  52. package/dist/types/components/fillsheet/fillsheet.d.ts +165 -0
  53. package/dist/types/components/fillsheet/fillsheet.recipe.d.ts +202 -0
  54. package/dist/types/components/fillsheet/index.d.ts +3 -0
  55. package/dist/types/components/fillsheet/serialize.d.ts +45 -0
  56. package/dist/types/index.d.ts +2 -0
  57. package/dist/types/product/recordpanel/recordpanel.d.ts +11 -1
  58. package/dist/types/product/sidebar/sidebar.d.ts +56 -0
  59. package/package.json +11 -1
@@ -0,0 +1,31 @@
1
+ @layer crisp-components {
2
+ .crisp-fillsheet {
3
+ display: grid; grid-template-columns: var(--crisp-fillsheet-cols); grid-template-rows: var(--crisp-fillsheet-rows); position: relative; overflow: auto; max-width: 100%; box-sizing: border-box; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); border-radius: 0; border: 1px solid var(--crisp-border-default); user-select: none; -webkit-user-select: none;
4
+ &:focus, &:focus-visible { outline: none; }
5
+ & .crisp-fillsheet-cell { position: relative; display: flex; align-items: flex-start; min-width: 0; padding-inline: var(--crisp-space-3); padding-block: var(--crisp-space-3); border-inline-end: 1px solid var(--crisp-border-default); border-block-end: 1px solid var(--crisp-border-default); background: var(--crisp-bg-surface); white-space: pre-wrap; overflow-wrap: break-word; line-height: 20px; cursor: cell; }
6
+ & .crisp-fillsheet-cell[aria-readonly] { background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
7
+ & .crisp-fillsheet-cell:last-child { border-inline-end: none; }
8
+ & > div:last-child .crisp-fillsheet-cell { border-block-end: none; }
9
+ & .crisp-fillsheet-cell[data-align="end"] { justify-content: flex-end; font-variant-numeric: tabular-nums; }
10
+ &[data-multi] .crisp-fillsheet-cell[data-range] { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
11
+ &[data-keynav] .crisp-fillsheet-cell[data-selected] { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); box-shadow: inset 0 -2px 0 var(--crisp-fg-primary); }
12
+ & .crisp-fillsheet-cell[data-editing] { background: var(--crisp-bg-surface); }
13
+ & .crisp-fillsheet-colresize { position: absolute; inset-block-start: 0; inset-block-end: 0; inset-inline-end: 0; z-index: 3; width: 5px; cursor: col-resize; touch-action: none; }
14
+ & .crisp-fillsheet-rowresize { position: absolute; inset-inline-start: 0; inset-inline-end: 0; inset-block-end: 0; z-index: 3; height: 5px; cursor: row-resize; touch-action: none; }
15
+ & .crisp-fillsheet-colresize:hover { background: linear-gradient(to right, transparent 0, transparent calc(50% - 1px), var(--crisp-fg-primary) calc(50% - 1px), var(--crisp-fg-primary) calc(50% + 1px), transparent calc(50% + 1px)); }
16
+ & .crisp-fillsheet-rowresize:hover { background: linear-gradient(to bottom, transparent 0, transparent calc(50% - 1px), var(--crisp-fg-primary) calc(50% - 1px), var(--crisp-fg-primary) calc(50% + 1px), transparent calc(50% + 1px)); }
17
+ & .crisp-fillsheet-editor { display: block; flex-grow: 1; width: 100%; min-width: 0; margin: 0; padding: 0; border: none; outline: none; background: transparent; font-family: inherit; font-size: inherit; line-height: 20px; color: inherit; resize: none; user-select: text; -webkit-user-select: text; overflow: hidden; }
18
+ & .crisp-fillsheet-select .crisp-select-trigger { width: 100%; height: 100%; padding: 0; border: none; background: transparent; box-shadow: none; font: inherit; color: inherit; }
19
+ & .crisp-fillsheet-select .crisp-select-trigger:hover, & .crisp-fillsheet-select .crisp-select-trigger[data-open] { background: transparent; box-shadow: none; }
20
+ & .crisp-fillsheet-select .crisp-select-chevron { display: none; }
21
+ }
22
+ .crisp-fillsheet--surface_panel {
23
+
24
+ }
25
+ .crisp-fillsheet--surface_paper {
26
+ box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
27
+ }
28
+ .crisp-fillsheet--surface_bare {
29
+ border: none;
30
+ }
31
+ }
@@ -25,6 +25,12 @@
25
25
  & .crisp-recordstable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent); }
26
26
  & .crisp-recordpanel-link { color: var(--crisp-bg-brand-solid); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
27
27
  & .crisp-recordpanel-link:hover { text-decoration: underline; }
28
+ /* #329: an optional slot for record actions (e.g. Edit). Reuses the header's own measured values rather than inventing new ones -- the
29
+ same horizontal inset (space.3), the same hairline border token
30
+ (borderSubtle, flipped to border-top since this sits at the opposite
31
+ edge), and the header/body gap (space.2) for its own vertical padding
32
+ and for spacing between whatever it's given. */
33
+ & .crisp-recordpanel-footer { flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-2); padding: var(--crisp-space-2) var(--crisp-space-3); border-top: 1px solid var(--crisp-border-subtle); }
28
34
  }
29
35
 
30
36
  @media (prefers-reduced-motion: reduce) {
@@ -26,6 +26,12 @@
26
26
  & .crisp-recordstable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent); }
27
27
  & .crisp-recordpanel-link { color: var(--crisp-bg-brand-solid); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
28
28
  & .crisp-recordpanel-link:hover { text-decoration: underline; }
29
+ /* #329: an optional slot for record actions (e.g. Edit). Reuses the header's own measured values rather than inventing new ones -- the
30
+ same horizontal inset (space.3), the same hairline border token
31
+ (borderSubtle, flipped to border-top since this sits at the opposite
32
+ edge), and the header/body gap (space.2) for its own vertical padding
33
+ and for spacing between whatever it's given. */
34
+ & .crisp-recordpanel-footer { flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-2); padding: var(--crisp-space-2) var(--crisp-space-3); border-top: 1px solid var(--crisp-border-subtle); }
29
35
  }
30
36
 
31
37
  @media (prefers-reduced-motion: reduce) {
package/dist/styles.css CHANGED
@@ -283,6 +283,9 @@
283
283
  & .crisp-bulkbar-count { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-menuRow); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
284
284
  & .crisp-bulkbar-count:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); color: var(--crisp-fg-primary); }
285
285
  & .crisp-bulkbar-count svg { flex-shrink: 0; }
286
+ /* the ", Clear selection" ARIA concatenates onto the pill's name (#324)
287
+ -- read, never drawn. Same technique as Slider's thumblabel. */
288
+ & .crisp-bulkbar-clearlabel { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
286
289
  & .crisp-bulkbar-btn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
287
290
  & .crisp-bulkbar-btn:hover { background: var(--crisp-bg-raised); }
288
291
  & .crisp-bulkbar-btn--danger { color: var(--crisp-bg-danger); }
@@ -511,6 +514,8 @@
511
514
  & tbody tr[data-selected] td[data-sticky] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
512
515
  & tbody tr:hover td[data-sticky] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
513
516
  & .crisp-table-scroll[data-scrolled-x] [data-sticky-edge] { clip-path: inset(0 -38px 0 0); box-shadow: 6px 0 16px 4px rgba(0,0,0,0.12); }
517
+ /* mirror of the rule above, for stickyLast's trailing column (#327) */
518
+ & .crisp-table-scroll[data-scrolled-x-end] [data-sticky-edge-end] { clip-path: inset(0 0 0 -38px); box-shadow: -6px 0 16px 4px rgba(0,0,0,0.12); }
514
519
  /* add-row + summary footer */
515
520
  & .crisp-datatable-addcell { padding: 0; border-top: none; }
516
521
  & .crisp-datatable-addrow { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); border: none; border-top: 1px solid var(--crisp-border-subtle); background: var(--crisp-bg-surface); color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); cursor: pointer; transition: background-color .12s; }
@@ -534,7 +539,12 @@
534
539
  & .crisp-datatable-entity { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; color: var(--crisp-fg-primary); font-weight: var(--crisp-weight-medium); }
535
540
  & .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
536
541
  & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: var(--crisp-radius-sm); flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
537
- & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); } & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); } & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); } & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); } & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); } & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
542
+ & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
543
+ & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
544
+ & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
545
+ & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
546
+ & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
547
+ & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
538
548
  & .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
539
549
  & .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
540
550
  & .crisp-datatable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
@@ -547,10 +557,11 @@
547
557
  & .crisp-datatable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); }
548
558
  & .crisp-datatable-num { font-variant-numeric: tabular-nums; }
549
559
  & .crisp-datatable-muted { color: var(--crisp-fg-muted); }
550
- /* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
551
- a leading 20px grip column, a 16px grip icon, and the row's own hairline doubling as the drop indicator (it tints toward the brand colour as the active drop target). The affordance + geometry are measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
552
- draggable + dataTransfer, the same one column reorder already uses
553
- (RecordsTable's reorderColumn) -- not a proprietary pointer-events implementation. */
560
+ /* row drag-to-reorder -- a Settings > Objects > Attributes screen measures a leading 20px grip column, a 16px grip icon, and the row's own
561
+ hairline doubling as the drop indicator (it tints toward the brand
562
+ colour as the active drop target). The affordance + geometry are
563
+ measured; the drag MECHANISM is crisp's existing house idiom -- HTML5 draggable + dataTransfer, the same one column reorder already uses (RecordsTable's reorderColumn) -- not a proprietary
564
+ pointer-events implementation. */
554
565
  & .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
555
566
  & .crisp-datatable-grip { display: inline-flex; align-items: center; justify-content: center; width: 100%; height: 100%; margin: 0; border: none; border-radius: 0; background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: grab; }
556
567
  & .crisp-datatable-grip:active { cursor: grabbing; }
@@ -836,6 +847,68 @@
836
847
  }
837
848
  }
838
849
 
850
+ .crisp-filldoc {
851
+ display: flex; flex-direction: column; gap: var(--crisp-space-4); box-sizing: border-box; width: 210mm; min-height: 297mm; padding: 20mm; margin: 0 auto; background: var(--crisp-bg-surface); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 22px; color: var(--crisp-fg-primary); border-radius: 0; box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
852
+ &:focus, &:focus-visible { outline: none; }
853
+ & .crisp-filldoc-block { position: relative; }
854
+ & .crisp-filldoc-heading { margin: 0; font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-semibold); line-height: 26px; color: var(--crisp-fg-primary); white-space: pre-wrap; overflow-wrap: break-word; }
855
+ & .crisp-filldoc-text { margin: 0; font-size: var(--crisp-text-lg); line-height: 22px; color: var(--crisp-fg-primary); white-space: pre-wrap; overflow-wrap: break-word; }
856
+ & .crisp-filldoc-writer { display: block; width: 100%; margin: 0; padding: 0; border: none; outline: none; background: transparent; font-family: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; color: inherit; resize: none; overflow: hidden; user-select: text; -webkit-user-select: text; }
857
+ & .crisp-filldoc-insert { position: absolute; inset-inline-start: 0; inset-inline-end: 0; inset-block-end: calc(var(--crisp-space-4) / -2); height: var(--crisp-space-4); display: flex; align-items: center; gap: var(--crisp-space-2); opacity: 0; transition: opacity .1s; cursor: pointer; }
858
+ & .crisp-filldoc-block:hover .crisp-filldoc-insert, & .crisp-filldoc-insert:focus-within { opacity: 1; }
859
+ & .crisp-filldoc-insert-rule { flex: 1; height: 1px; background: var(--crisp-border-default); }
860
+ & .crisp-filldoc-insert button { display: inline-flex; align-items: center; height: 20px; padding: 0 var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-raised); font-family: inherit; font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); cursor: pointer; }
861
+ & .crisp-filldoc-insert button:hover { background: var(--crisp-bg-neutral-weak); color: var(--crisp-fg-primary); }
862
+ & .crisp-filldoc-tools { position: absolute; inset-inline-end: 100%; inset-block-start: 0; padding-inline-end: var(--crisp-space-2); display: flex; gap: var(--crisp-space-1); opacity: 0; transition: opacity .1s; }
863
+ & .crisp-filldoc-block:hover .crisp-filldoc-tools, & .crisp-filldoc-tools:focus-within { opacity: 1; }
864
+ & .crisp-filldoc-tools button { width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: transparent; font-family: inherit; font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); cursor: pointer; }
865
+ & .crisp-filldoc-tools button:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
866
+ }
867
+ .crisp-filldoc--page_a4 {
868
+
869
+ }
870
+ .crisp-filldoc--page_auto {
871
+ width: 100%; min-height: 0; max-width: 210mm;
872
+ }
873
+
874
+ @media (prefers-reduced-motion: reduce) {
875
+ .crisp-filldoc, .crisp-filldoc * {
876
+ animation-duration: 0.01ms !important;
877
+ animation-iteration-count: 1 !important;
878
+ transition-duration: 0.01ms !important;
879
+ }
880
+ }
881
+
882
+ .crisp-fillsheet {
883
+ display: grid; grid-template-columns: var(--crisp-fillsheet-cols); grid-template-rows: var(--crisp-fillsheet-rows); position: relative; overflow: auto; max-width: 100%; box-sizing: border-box; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); border-radius: 0; border: 1px solid var(--crisp-border-default); user-select: none; -webkit-user-select: none;
884
+ &:focus, &:focus-visible { outline: none; }
885
+ & .crisp-fillsheet-cell { position: relative; display: flex; align-items: flex-start; min-width: 0; padding-inline: var(--crisp-space-3); padding-block: var(--crisp-space-3); border-inline-end: 1px solid var(--crisp-border-default); border-block-end: 1px solid var(--crisp-border-default); background: var(--crisp-bg-surface); white-space: pre-wrap; overflow-wrap: break-word; line-height: 20px; cursor: cell; }
886
+ & .crisp-fillsheet-cell[aria-readonly] { background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
887
+ & .crisp-fillsheet-cell:last-child { border-inline-end: none; }
888
+ & > div:last-child .crisp-fillsheet-cell { border-block-end: none; }
889
+ & .crisp-fillsheet-cell[data-align="end"] { justify-content: flex-end; font-variant-numeric: tabular-nums; }
890
+ &[data-multi] .crisp-fillsheet-cell[data-range] { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
891
+ &[data-keynav] .crisp-fillsheet-cell[data-selected] { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); box-shadow: inset 0 -2px 0 var(--crisp-fg-primary); }
892
+ & .crisp-fillsheet-cell[data-editing] { background: var(--crisp-bg-surface); }
893
+ & .crisp-fillsheet-colresize { position: absolute; inset-block-start: 0; inset-block-end: 0; inset-inline-end: 0; z-index: 3; width: 5px; cursor: col-resize; touch-action: none; }
894
+ & .crisp-fillsheet-rowresize { position: absolute; inset-inline-start: 0; inset-inline-end: 0; inset-block-end: 0; z-index: 3; height: 5px; cursor: row-resize; touch-action: none; }
895
+ & .crisp-fillsheet-colresize:hover { background: linear-gradient(to right, transparent 0, transparent calc(50% - 1px), var(--crisp-fg-primary) calc(50% - 1px), var(--crisp-fg-primary) calc(50% + 1px), transparent calc(50% + 1px)); }
896
+ & .crisp-fillsheet-rowresize:hover { background: linear-gradient(to bottom, transparent 0, transparent calc(50% - 1px), var(--crisp-fg-primary) calc(50% - 1px), var(--crisp-fg-primary) calc(50% + 1px), transparent calc(50% + 1px)); }
897
+ & .crisp-fillsheet-editor { display: block; flex-grow: 1; width: 100%; min-width: 0; margin: 0; padding: 0; border: none; outline: none; background: transparent; font-family: inherit; font-size: inherit; line-height: 20px; color: inherit; resize: none; user-select: text; -webkit-user-select: text; overflow: hidden; }
898
+ & .crisp-fillsheet-select .crisp-select-trigger { width: 100%; height: 100%; padding: 0; border: none; background: transparent; box-shadow: none; font: inherit; color: inherit; }
899
+ & .crisp-fillsheet-select .crisp-select-trigger:hover, & .crisp-fillsheet-select .crisp-select-trigger[data-open] { background: transparent; box-shadow: none; }
900
+ & .crisp-fillsheet-select .crisp-select-chevron { display: none; }
901
+ }
902
+ .crisp-fillsheet--surface_panel {
903
+
904
+ }
905
+ .crisp-fillsheet--surface_paper {
906
+ box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
907
+ }
908
+ .crisp-fillsheet--surface_bare {
909
+ border: none;
910
+ }
911
+
839
912
  .crisp-formfield {
840
913
  display: flex; flex-direction: column; gap: var(--crisp-space-1-5); box-sizing: border-box; font-family: var(--crisp-font-sans);
841
914
  & .crisp-formfield-label { display: inline-flex; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -1992,6 +2065,12 @@
1992
2065
  & .crisp-recordstable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent); }
1993
2066
  & .crisp-recordpanel-link { color: var(--crisp-bg-brand-solid); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
1994
2067
  & .crisp-recordpanel-link:hover { text-decoration: underline; }
2068
+ /* #329: an optional slot for record actions (e.g. Edit). Reuses the header's own measured values rather than inventing new ones -- the
2069
+ same horizontal inset (space.3), the same hairline border token
2070
+ (borderSubtle, flipped to border-top since this sits at the opposite
2071
+ edge), and the header/body gap (space.2) for its own vertical padding
2072
+ and for spacing between whatever it's given. */
2073
+ & .crisp-recordpanel-footer { flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-2); padding: var(--crisp-space-2) var(--crisp-space-3); border-top: 1px solid var(--crisp-border-subtle); }
1995
2074
  }
1996
2075
 
1997
2076
  @media (prefers-reduced-motion: reduce) {
@@ -284,6 +284,9 @@
284
284
  & .crisp-bulkbar-count { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-menuRow); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
285
285
  & .crisp-bulkbar-count:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); color: var(--crisp-fg-primary); }
286
286
  & .crisp-bulkbar-count svg { flex-shrink: 0; }
287
+ /* the ", Clear selection" ARIA concatenates onto the pill's name (#324)
288
+ -- read, never drawn. Same technique as Slider's thumblabel. */
289
+ & .crisp-bulkbar-clearlabel { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
287
290
  & .crisp-bulkbar-btn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-menuRow); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: transparent; color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
288
291
  & .crisp-bulkbar-btn:hover { background: var(--crisp-bg-raised); }
289
292
  & .crisp-bulkbar-btn--danger { color: var(--crisp-bg-danger); }
@@ -512,6 +515,8 @@
512
515
  & tbody tr[data-selected] td[data-sticky] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 10%, var(--crisp-bg-surface)); }
513
516
  & tbody tr:hover td[data-sticky] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
514
517
  & .crisp-table-scroll[data-scrolled-x] [data-sticky-edge] { clip-path: inset(0 -38px 0 0); box-shadow: 6px 0 16px 4px rgba(0,0,0,0.12); }
518
+ /* mirror of the rule above, for stickyLast's trailing column (#327) */
519
+ & .crisp-table-scroll[data-scrolled-x-end] [data-sticky-edge-end] { clip-path: inset(0 0 0 -38px); box-shadow: -6px 0 16px 4px rgba(0,0,0,0.12); }
515
520
  /* add-row + summary footer */
516
521
  & .crisp-datatable-addcell { padding: 0; border-top: none; }
517
522
  & .crisp-datatable-addrow { display: flex; align-items: center; gap: var(--crisp-space-2); width: 100%; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-2); border: none; border-top: 1px solid var(--crisp-border-subtle); background: var(--crisp-bg-surface); color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); cursor: pointer; transition: background-color .12s; }
@@ -535,7 +540,12 @@
535
540
  & .crisp-datatable-entity { display: flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; color: var(--crisp-fg-primary); font-weight: var(--crisp-weight-medium); }
536
541
  & .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
537
542
  & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: var(--crisp-radius-sm); flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
538
- & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); } & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); } & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); } & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); } & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); } & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
543
+ & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
544
+ & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
545
+ & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
546
+ & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
547
+ & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
548
+ & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
539
549
  & .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
540
550
  & .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
541
551
  & .crisp-datatable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
@@ -548,10 +558,11 @@
548
558
  & .crisp-datatable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); }
549
559
  & .crisp-datatable-num { font-variant-numeric: tabular-nums; }
550
560
  & .crisp-datatable-muted { color: var(--crisp-fg-muted); }
551
- /* row drag-to-reorder -- a Settings > Objects > Attributes screen measures
552
- a leading 20px grip column, a 16px grip icon, and the row's own hairline doubling as the drop indicator (it tints toward the brand colour as the active drop target). The affordance + geometry are measured; the drag MECHANISM is crisp's existing house idiom -- HTML5
553
- draggable + dataTransfer, the same one column reorder already uses
554
- (RecordsTable's reorderColumn) -- not a proprietary pointer-events implementation. */
561
+ /* row drag-to-reorder -- a Settings > Objects > Attributes screen measures a leading 20px grip column, a 16px grip icon, and the row's own
562
+ hairline doubling as the drop indicator (it tints toward the brand
563
+ colour as the active drop target). The affordance + geometry are
564
+ measured; the drag MECHANISM is crisp's existing house idiom -- HTML5 draggable + dataTransfer, the same one column reorder already uses (RecordsTable's reorderColumn) -- not a proprietary
565
+ pointer-events implementation. */
555
566
  & .crisp-datatable-col-grip { width: 20px; padding: 0; text-align: center; }
556
567
  & .crisp-datatable-grip { display: inline-flex; align-items: center; justify-content: center; width: 100%; height: 100%; margin: 0; border: none; border-radius: 0; background: none; font-family: inherit; color: var(--crisp-fg-muted); cursor: grab; }
557
568
  & .crisp-datatable-grip:active { cursor: grabbing; }
@@ -837,6 +848,68 @@
837
848
  }
838
849
  }
839
850
 
851
+ .crisp-filldoc {
852
+ display: flex; flex-direction: column; gap: var(--crisp-space-4); box-sizing: border-box; width: 210mm; min-height: 297mm; padding: 20mm; margin: 0 auto; background: var(--crisp-bg-surface); font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); line-height: 22px; color: var(--crisp-fg-primary); border-radius: 0; box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
853
+ &:focus, &:focus-visible { outline: none; }
854
+ & .crisp-filldoc-block { position: relative; }
855
+ & .crisp-filldoc-heading { margin: 0; font-size: var(--crisp-text-xl); font-weight: var(--crisp-weight-semibold); line-height: 26px; color: var(--crisp-fg-primary); white-space: pre-wrap; overflow-wrap: break-word; }
856
+ & .crisp-filldoc-text { margin: 0; font-size: var(--crisp-text-lg); line-height: 22px; color: var(--crisp-fg-primary); white-space: pre-wrap; overflow-wrap: break-word; }
857
+ & .crisp-filldoc-writer { display: block; width: 100%; margin: 0; padding: 0; border: none; outline: none; background: transparent; font-family: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; color: inherit; resize: none; overflow: hidden; user-select: text; -webkit-user-select: text; }
858
+ & .crisp-filldoc-insert { position: absolute; inset-inline-start: 0; inset-inline-end: 0; inset-block-end: calc(var(--crisp-space-4) / -2); height: var(--crisp-space-4); display: flex; align-items: center; gap: var(--crisp-space-2); opacity: 0; transition: opacity .1s; cursor: pointer; }
859
+ & .crisp-filldoc-block:hover .crisp-filldoc-insert, & .crisp-filldoc-insert:focus-within { opacity: 1; }
860
+ & .crisp-filldoc-insert-rule { flex: 1; height: 1px; background: var(--crisp-border-default); }
861
+ & .crisp-filldoc-insert button { display: inline-flex; align-items: center; height: 20px; padding: 0 var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-sm); background: var(--crisp-bg-raised); font-family: inherit; font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); cursor: pointer; }
862
+ & .crisp-filldoc-insert button:hover { background: var(--crisp-bg-neutral-weak); color: var(--crisp-fg-primary); }
863
+ & .crisp-filldoc-tools { position: absolute; inset-inline-end: 100%; inset-block-start: 0; padding-inline-end: var(--crisp-space-2); display: flex; gap: var(--crisp-space-1); opacity: 0; transition: opacity .1s; }
864
+ & .crisp-filldoc-block:hover .crisp-filldoc-tools, & .crisp-filldoc-tools:focus-within { opacity: 1; }
865
+ & .crisp-filldoc-tools button { width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: transparent; font-family: inherit; font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); cursor: pointer; }
866
+ & .crisp-filldoc-tools button:hover { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
867
+ }
868
+ .crisp-filldoc--page_a4 {
869
+
870
+ }
871
+ .crisp-filldoc--page_auto {
872
+ width: 100%; min-height: 0; max-width: 210mm;
873
+ }
874
+
875
+ @media (prefers-reduced-motion: reduce) {
876
+ .crisp-filldoc, .crisp-filldoc * {
877
+ animation-duration: 0.01ms !important;
878
+ animation-iteration-count: 1 !important;
879
+ transition-duration: 0.01ms !important;
880
+ }
881
+ }
882
+
883
+ .crisp-fillsheet {
884
+ display: grid; grid-template-columns: var(--crisp-fillsheet-cols); grid-template-rows: var(--crisp-fillsheet-rows); position: relative; overflow: auto; max-width: 100%; box-sizing: border-box; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); border-radius: 0; border: 1px solid var(--crisp-border-default); user-select: none; -webkit-user-select: none;
885
+ &:focus, &:focus-visible { outline: none; }
886
+ & .crisp-fillsheet-cell { position: relative; display: flex; align-items: flex-start; min-width: 0; padding-inline: var(--crisp-space-3); padding-block: var(--crisp-space-3); border-inline-end: 1px solid var(--crisp-border-default); border-block-end: 1px solid var(--crisp-border-default); background: var(--crisp-bg-surface); white-space: pre-wrap; overflow-wrap: break-word; line-height: 20px; cursor: cell; }
887
+ & .crisp-fillsheet-cell[aria-readonly] { background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
888
+ & .crisp-fillsheet-cell:last-child { border-inline-end: none; }
889
+ & > div:last-child .crisp-fillsheet-cell { border-block-end: none; }
890
+ & .crisp-fillsheet-cell[data-align="end"] { justify-content: flex-end; font-variant-numeric: tabular-nums; }
891
+ &[data-multi] .crisp-fillsheet-cell[data-range] { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); }
892
+ &[data-keynav] .crisp-fillsheet-cell[data-selected] { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); box-shadow: inset 0 -2px 0 var(--crisp-fg-primary); }
893
+ & .crisp-fillsheet-cell[data-editing] { background: var(--crisp-bg-surface); }
894
+ & .crisp-fillsheet-colresize { position: absolute; inset-block-start: 0; inset-block-end: 0; inset-inline-end: 0; z-index: 3; width: 5px; cursor: col-resize; touch-action: none; }
895
+ & .crisp-fillsheet-rowresize { position: absolute; inset-inline-start: 0; inset-inline-end: 0; inset-block-end: 0; z-index: 3; height: 5px; cursor: row-resize; touch-action: none; }
896
+ & .crisp-fillsheet-colresize:hover { background: linear-gradient(to right, transparent 0, transparent calc(50% - 1px), var(--crisp-fg-primary) calc(50% - 1px), var(--crisp-fg-primary) calc(50% + 1px), transparent calc(50% + 1px)); }
897
+ & .crisp-fillsheet-rowresize:hover { background: linear-gradient(to bottom, transparent 0, transparent calc(50% - 1px), var(--crisp-fg-primary) calc(50% - 1px), var(--crisp-fg-primary) calc(50% + 1px), transparent calc(50% + 1px)); }
898
+ & .crisp-fillsheet-editor { display: block; flex-grow: 1; width: 100%; min-width: 0; margin: 0; padding: 0; border: none; outline: none; background: transparent; font-family: inherit; font-size: inherit; line-height: 20px; color: inherit; resize: none; user-select: text; -webkit-user-select: text; overflow: hidden; }
899
+ & .crisp-fillsheet-select .crisp-select-trigger { width: 100%; height: 100%; padding: 0; border: none; background: transparent; box-shadow: none; font: inherit; color: inherit; }
900
+ & .crisp-fillsheet-select .crisp-select-trigger:hover, & .crisp-fillsheet-select .crisp-select-trigger[data-open] { background: transparent; box-shadow: none; }
901
+ & .crisp-fillsheet-select .crisp-select-chevron { display: none; }
902
+ }
903
+ .crisp-fillsheet--surface_panel {
904
+
905
+ }
906
+ .crisp-fillsheet--surface_paper {
907
+ box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3);
908
+ }
909
+ .crisp-fillsheet--surface_bare {
910
+ border: none;
911
+ }
912
+
840
913
  .crisp-formfield {
841
914
  display: flex; flex-direction: column; gap: var(--crisp-space-1-5); box-sizing: border-box; font-family: var(--crisp-font-sans);
842
915
  & .crisp-formfield-label { display: inline-flex; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -1993,6 +2066,12 @@
1993
2066
  & .crisp-recordstable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-bg-orange) 30%, transparent); }
1994
2067
  & .crisp-recordpanel-link { color: var(--crisp-bg-brand-solid); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
1995
2068
  & .crisp-recordpanel-link:hover { text-decoration: underline; }
2069
+ /* #329: an optional slot for record actions (e.g. Edit). Reuses the header's own measured values rather than inventing new ones -- the
2070
+ same horizontal inset (space.3), the same hairline border token
2071
+ (borderSubtle, flipped to border-top since this sits at the opposite
2072
+ edge), and the header/body gap (space.2) for its own vertical padding
2073
+ and for spacing between whatever it's given. */
2074
+ & .crisp-recordpanel-footer { flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-2); padding: var(--crisp-space-2) var(--crisp-space-3); border-top: 1px solid var(--crisp-border-subtle); }
1996
2075
  }
1997
2076
 
1998
2077
  @media (prefers-reduced-motion: reduce) {
@@ -129,6 +129,12 @@ export type DataTableProps<T extends {
129
129
  onEdit?: (id: string, key: string, value: string) => void;
130
130
  /** Sticky the first column(s) with a horizontal scroll shadow (default true). */
131
131
  stickyFirst?: boolean;
132
+ /** Sticky the LAST column with a horizontal scroll shadow, mirroring
133
+ * `stickyFirst` (default false — additive, so an existing table's trailing
134
+ * column doesn't start pinning without being asked). Follows reading
135
+ * direction like `stickyFirst` does: it pins to the trailing edge, which is
136
+ * the left edge under `dir="rtl"` (#288). */
137
+ stickyLast?: boolean;
132
138
  /** BCP 47 locale for the built-in `date`/`number`/`currency` renderers
133
139
  * (default "en-US"). Formats the date and groups the number the way that
134
140
  * locale's readers expect — e.g. "mn-MN" renders a date as "2026.09.12"
@@ -163,7 +169,7 @@ export type DataTableProps<T extends {
163
169
  };
164
170
  export declare function DataTable<T extends {
165
171
  id: string;
166
- }>({ columns: columnsProp, data, selectable, selectedIds, onSelectionChange, selectAllLabel, selectRowLabel, selectionAnnouncement, columnMenu, onColumnsChange, groupBy, onRowsReorder, error, sort: sortProp, defaultSort, onSortChange, filterable, searchPlaceholder, searchLabel, onEdit, stickyFirst, locale: localeProp, avatarTone, surface, interactive, onRowClick, onAddRow, addRowLabel, empty, showCount, countLabel, toolbar, className, reorderRowLabel, ...rest }: DataTableProps<T>): React.JSX.Element;
172
+ }>({ columns: columnsProp, data, selectable, selectedIds, onSelectionChange, selectAllLabel, selectRowLabel, selectionAnnouncement, columnMenu, onColumnsChange, groupBy, onRowsReorder, error, sort: sortProp, defaultSort, onSortChange, filterable, searchPlaceholder, searchLabel, onEdit, stickyFirst, stickyLast, locale: localeProp, avatarTone, surface, interactive, onRowClick, onAddRow, addRowLabel, empty, showCount, countLabel, toolbar, className, reorderRowLabel, ...rest }: DataTableProps<T>): React.JSX.Element;
167
173
  export declare namespace DataTable {
168
174
  var displayName: string;
169
175
  }
@@ -0,0 +1,79 @@
1
+ import * as React from "react";
2
+ import { type FillSheetColumn } from "../fillsheet";
3
+ /** A heading, a paragraph, or a sheet. */
4
+ export type FillDocBlock = {
5
+ id: string;
6
+ type: "heading";
7
+ text: string;
8
+ } | {
9
+ id: string;
10
+ type: "text";
11
+ text: string;
12
+ } | {
13
+ id: string;
14
+ type: "table";
15
+ columns: FillSheetColumn[];
16
+ value: string[][];
17
+ /** The sheet's accessible name; see FillSheet's `label`. */
18
+ label?: string;
19
+ };
20
+ export type FillDocProps = {
21
+ /** The document, in order. */
22
+ blocks: FillDocBlock[];
23
+ /** Every edit comes back through here — typing, inserting, removing. */
24
+ onBlocksChange?: (next: FillDocBlock[]) => void;
25
+ /**
26
+ * `edit` is the person who MAKES the document: they can type anywhere and
27
+ * add or remove blocks. `fill` is the person who fills it in — the prose is
28
+ * fixed and only the sheets take input.
29
+ */
30
+ mode?: "edit" | "fill";
31
+ /** `a4` is a real page; `auto` grows to its content. */
32
+ page?: "a4" | "auto";
33
+ /** The document's accessible name. No English default — see FillSheet. */
34
+ label?: string;
35
+ /** Copy for the insert controls. English defaults, overridable. */
36
+ addTextLabel?: string;
37
+ addHeadingLabel?: string;
38
+ addTableLabel?: string;
39
+ removeLabel?: string;
40
+ className?: string;
41
+ style?: React.CSSProperties;
42
+ } & Omit<React.HTMLAttributes<HTMLDivElement>, "onChange" | "children">;
43
+ /**
44
+ * A page you can write on, of which a sheet is one block.
45
+ *
46
+ * FillSheet is the table; this is the document it sits in. The two share a
47
+ * look on purpose -- a real page, real margins, square corners, and nothing
48
+ * drawn that is not content -- and the same split between the person who
49
+ * MAKES a form and the person who fills it in: in `edit` you write the prose
50
+ * and add or remove blocks, in `fill` the prose is fixed and only the sheets
51
+ * take input.
52
+ *
53
+ * Every block's controls are hidden until the pointer is in that block. A
54
+ * page covered in handles and grips stops looking like a page, which is the
55
+ * whole thing this is for.
56
+ */
57
+ export declare const FillDoc: React.ForwardRefExoticComponent<{
58
+ /** The document, in order. */
59
+ blocks: FillDocBlock[];
60
+ /** Every edit comes back through here — typing, inserting, removing. */
61
+ onBlocksChange?: (next: FillDocBlock[]) => void;
62
+ /**
63
+ * `edit` is the person who MAKES the document: they can type anywhere and
64
+ * add or remove blocks. `fill` is the person who fills it in — the prose is
65
+ * fixed and only the sheets take input.
66
+ */
67
+ mode?: "edit" | "fill";
68
+ /** `a4` is a real page; `auto` grows to its content. */
69
+ page?: "a4" | "auto";
70
+ /** The document's accessible name. No English default — see FillSheet. */
71
+ label?: string;
72
+ /** Copy for the insert controls. English defaults, overridable. */
73
+ addTextLabel?: string;
74
+ addHeadingLabel?: string;
75
+ addTableLabel?: string;
76
+ removeLabel?: string;
77
+ className?: string;
78
+ style?: React.CSSProperties;
79
+ } & Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & React.RefAttributes<HTMLDivElement>>;