@papernote/ui 1.0.0 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papernote/ui",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "A modern React component library with a paper notebook aesthetic - minimal, professional, and expressive",
6
6
  "main": "dist/index.js",
@@ -31,8 +31,12 @@
31
31
  "test:watch": "jest --watch",
32
32
  "test:coverage": "jest --coverage",
33
33
  "prepublishOnly": "npm run build",
34
+ "prerelease": "bash scripts/pre-publish-check.sh",
34
35
  "storybook": "storybook dev -p 6006",
35
- "build-storybook": "storybook build"
36
+ "build-storybook": "storybook build",
37
+ "docs:dev": "vitepress dev docs-site",
38
+ "docs:build": "vitepress build docs-site",
39
+ "docs:preview": "vitepress preview docs-site"
36
40
  },
37
41
  "peerDependencies": {
38
42
  "lucide-react": "^0.553.0",
@@ -64,6 +68,7 @@
64
68
  "jest-environment-jsdom": "^30.2.0",
65
69
  "lucide-react": "^0.554.0",
66
70
  "postcss": "^8.4.0",
71
+ "postcss-import": "^16.1.1",
67
72
  "react": "^19.2.0",
68
73
  "react-dom": "^19.2.0",
69
74
  "react-router-dom": "^7.9.6",
@@ -76,7 +81,8 @@
76
81
  "ts-jest": "^29.4.5",
77
82
  "tslib": "^2.6.0",
78
83
  "typescript": "^5.0.0",
79
- "vite": "^7.2.4"
84
+ "vite": "^7.2.4",
85
+ "vitepress": "^1.6.4"
80
86
  },
81
87
  "keywords": [
82
88
  "react",
@@ -99,5 +105,9 @@
99
105
  "homepage": "https://github.com/kwhittenberger/papernote-ui#readme",
100
106
  "bugs": {
101
107
  "url": "https://github.com/kwhittenberger/papernote-ui/issues"
108
+ },
109
+ "dependencies": {
110
+ "react-spreadsheet": "^0.10.1",
111
+ "xlsx": "^0.18.5"
102
112
  }
103
113
  }
@@ -334,3 +334,90 @@ export const FullFeatured: Story = {
334
334
  ),
335
335
  },
336
336
  };
337
+
338
+ export const WithSecondaryRows: Story = {
339
+ args: {
340
+ data: sampleUsers,
341
+ columns: [
342
+ {
343
+ key: 'name',
344
+ header: 'Name',
345
+ sortable: true,
346
+ renderSecondary: (user: User) => (
347
+ <span className="text-xs text-ink-500">Member since {user.joinedAt}</span>
348
+ ),
349
+ },
350
+ {
351
+ key: 'email',
352
+ header: 'Email',
353
+ sortable: true,
354
+ renderSecondary: (user: User) => (
355
+ <span className="text-xs text-ink-500">{user.role}</span>
356
+ ),
357
+ },
358
+ {
359
+ key: 'status',
360
+ header: 'Status',
361
+ render: (user: User) => (
362
+ <Badge variant={user.status === 'active' ? 'success' : user.status === 'inactive' ? 'error' : 'warning'}>
363
+ {user.status}
364
+ </Badge>
365
+ ),
366
+ },
367
+ ],
368
+ selectable: true,
369
+ actions: [
370
+ {
371
+ label: 'Edit',
372
+ icon: <Edit className="h-4 w-4" />,
373
+ onClick: (user: User) => alert(`Edit ${user.name}`),
374
+ },
375
+ {
376
+ label: 'View',
377
+ icon: <Eye className="h-4 w-4" />,
378
+ onClick: (user: User) => alert(`View ${user.name}`),
379
+ },
380
+ ],
381
+ },
382
+ };
383
+
384
+ export const FullWidthWrappingText: Story = {
385
+ args: {
386
+ data: [
387
+ { id: '1', name: 'ADOBE Adobe Systems SAN JOSE CA - Expense - Monthly subscription for creative cloud services' },
388
+ { id: '2', name: 'AMAZON PRIME Amazon.com SEATTLE WA - Entertainment - Annual membership fee' },
389
+ { id: '3', name: 'SPOTIFY Spotify USA NEW YORK NY - Music streaming service monthly payment' },
390
+ { id: '4', name: 'NETFLIX Netflix.com LOS GATOS CA - Video streaming monthly subscription' },
391
+ { id: '5', name: 'MICROSOFT Microsoft Corporation REDMOND WA - Office 365 business subscription annual fee' },
392
+ ],
393
+ columns: [
394
+ {
395
+ key: 'name',
396
+ header: 'Transaction Name',
397
+ flex: 1,
398
+ },
399
+ ],
400
+ },
401
+ };
402
+
403
+ export const FullWidthWithSecondaryRow: Story = {
404
+ args: {
405
+ data: [
406
+ { id: '1', name: 'ADOBE Adobe Systems SAN JOSE CA - Expense', frequency: 'Monthly', amount: '$16.52' },
407
+ { id: '2', name: 'AMAZON PRIME Amazon.com SEATTLE WA - Entertainment', frequency: 'Monthly', amount: '$25.00' },
408
+ { id: '3', name: 'SPOTIFY Spotify USA NEW YORK NY - Music streaming service', frequency: 'Monthly', amount: '$9.99' },
409
+ { id: '4', name: 'NETFLIX Netflix.com LOS GATOS CA - Video streaming', frequency: 'Monthly', amount: '$15.49' },
410
+ { id: '5', name: 'MICROSOFT Microsoft Corporation REDMOND WA - Office 365 business subscription', frequency: 'Annual', amount: '$132.14' },
411
+ ],
412
+ columns: [
413
+ {
414
+ key: 'name',
415
+ header: 'Name',
416
+ flex: 1,
417
+ renderSecondary: (item: any) => (
418
+ <span className="text-xs text-ink-500">{item.frequency} • {item.amount}</span>
419
+ ),
420
+ },
421
+ ],
422
+ },
423
+ };
@@ -502,6 +502,9 @@ export default function DataTable<T extends BaseDataItem = BaseDataItem>({
502
502
  const [scrollTop, setScrollTop] = useState(0);
503
503
  const tableContainerRef = useRef<HTMLDivElement>(null);
504
504
 
505
+ // Row hover state (for coordinating primary + secondary row highlighting)
506
+ const [hoveredRowKey, setHoveredRowKey] = useState<string | null>(null);
507
+
505
508
  // Filter columns based on hiddenColumns
506
509
  const baseVisibleColumns = columns.filter(
507
510
  col => !hiddenColumns.includes(String(col.key))
@@ -980,50 +983,83 @@ export default function DataTable<T extends BaseDataItem = BaseDataItem>({
980
983
  const isSelected = selectedRowsSet.has(rowKey);
981
984
  const isExpanded = expandedRowsSet.has(rowKey);
982
985
  const rowBgClass = getRowBackgroundClass(item, index);
983
- const hoverClass = disableHover ? '' : 'hover:bg-paper-100';
984
986
  const borderClass = bordered ? `border-b ${borderColor}` : (!visibleColumns.some(col => !!col.renderSecondary) ? `border-b ${borderColor}` : '');
987
+ const hasSecondaryRow = visibleColumns.some(col => !!col.renderSecondary);
988
+
989
+ // Hover state for row pair (primary + secondary)
990
+ const isHovered = hoveredRowKey === rowKey;
991
+ const hoverClass = disableHover ? '' : (isHovered ? 'bg-paper-100' : '');
985
992
 
986
993
  return (
987
994
  <React.Fragment key={rowKey}>
988
995
  <tr
989
- className={`${hoverClass} table-row-stable ${onRowDoubleClick || onRowClick || (expandedRowConfig?.edit?.triggerOnDoubleClick !== false) || (expandedRowConfig?.details?.triggerOnDoubleClick === true) ? 'cursor-pointer' : ''} ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : rowBgClass} ${borderClass}`}
996
+ className={`table-row-stable ${onRowDoubleClick || onRowClick || onEdit || expandedRowConfig?.edit || expandedRowConfig?.details || expandedRowConfig?.addRelated?.length || expandedRowConfig?.manageRelated?.length ? 'cursor-pointer' : ''} ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} ${borderClass}`}
997
+ onMouseEnter={() => !disableHover && setHoveredRowKey(rowKey)}
998
+ onMouseLeave={() => !disableHover && setHoveredRowKey(null)}
990
999
  onClick={() => onRowClick?.(item)}
991
1000
  onDoubleClick={() => {
992
- // Check for edit mode with triggerOnDoubleClick
993
- if (expandedRowConfig?.edit && expandedRowConfig.edit.triggerOnDoubleClick !== false) {
1001
+ // Priority 1: If there's an onEdit handler (legacy), trigger it
1002
+ if (onEdit) {
1003
+ onEdit(item);
1004
+ }
1005
+ // Priority 2: If there's an expandable edit mode, trigger it
1006
+ else if (expandedRowConfig?.edit) {
994
1007
  handleExpansionWithMode(rowKey, 'edit');
995
1008
  }
996
- // Check for details mode with triggerOnDoubleClick
997
- else if (expandedRowConfig?.details && expandedRowConfig.details.triggerOnDoubleClick === true) {
1009
+ // Priority 3: If there's an expandable details mode, trigger it
1010
+ else if (expandedRowConfig?.details) {
998
1011
  handleExpansionWithMode(rowKey, 'details');
999
1012
  }
1000
- // Legacy: use onRowDoubleClick handler
1013
+ // Priority 4: If there's any addRelated mode, trigger the first one
1014
+ else if (expandedRowConfig?.addRelated && expandedRowConfig.addRelated.length > 0) {
1015
+ handleExpansionWithMode(rowKey, `addRelated-${expandedRowConfig.addRelated[0].key}`);
1016
+ }
1017
+ // Priority 5: If there's any manageRelated mode, trigger the first one
1018
+ else if (expandedRowConfig?.manageRelated && expandedRowConfig.manageRelated.length > 0) {
1019
+ handleExpansionWithMode(rowKey, `manageRelated-${expandedRowConfig.manageRelated[0].key}`);
1020
+ }
1021
+ // Priority 6: Legacy onRowDoubleClick handler
1001
1022
  else {
1002
1023
  onRowDoubleClick?.(item);
1003
1024
  }
1004
1025
  }}
1005
1026
  title={
1006
- expandedRowConfig?.edit && expandedRowConfig.edit.triggerOnDoubleClick !== false ? 'Double-click to edit inline' :
1007
- expandedRowConfig?.details && expandedRowConfig.details.triggerOnDoubleClick === true ? 'Double-click to view details' :
1008
- onRowDoubleClick ? 'Double-click to open details' :
1009
- onRowClick ? 'Click to select' :
1027
+ onEdit ? 'Double-click to edit' :
1028
+ expandedRowConfig?.edit ? 'Double-click to edit inline' :
1029
+ expandedRowConfig?.details ? 'Double-click to view details' :
1030
+ expandedRowConfig?.addRelated && expandedRowConfig.addRelated.length > 0 ? `Double-click to ${expandedRowConfig.addRelated[0].label}` :
1031
+ expandedRowConfig?.manageRelated && expandedRowConfig.manageRelated.length > 0 ? `Double-click to ${expandedRowConfig.manageRelated[0].label}` :
1032
+ onRowDoubleClick ? 'Double-click for details' :
1033
+ onRowClick ? 'Click to select' :
1010
1034
  undefined
1011
1035
  }
1012
1036
  >
1013
1037
  {selectable && (
1014
- <td className={`sticky left-0 bg-white ${currentDensity.cell} z-10 align-middle ${bordered ? `border ${borderColor}` : ''}`}>
1038
+ <td
1039
+ className={`sticky left-0 z-10 ${bordered ? `border ${borderColor}` : ''}`}
1040
+ style={{
1041
+ backgroundColor: 'inherit',
1042
+ verticalAlign: 'middle',
1043
+ padding: '0.375rem 0.75rem',
1044
+ textAlign: 'center'
1045
+ }}
1046
+ rowSpan={hasSecondaryRow ? 2 : 1}
1047
+ >
1015
1048
  <input
1016
1049
  type="checkbox"
1017
1050
  checked={isSelected}
1018
1051
  onChange={() => handleRowSelect(rowKey)}
1019
1052
  className="w-4 h-4 text-accent-600 border-paper-300 rounded focus:ring-accent-400"
1020
- style={{ verticalAlign: 'middle' }}
1021
1053
  aria-label={`Select row ${rowKey}`}
1022
1054
  />
1023
1055
  </td>
1024
1056
  )}
1025
1057
  {((expandable || expandedRowConfig) && showExpandChevron) && (
1026
- <td className={`sticky left-0 bg-white px-2 ${currentDensity.cell} z-10 ${bordered ? `border ${borderColor}` : ''}`}>
1058
+ <td
1059
+ className={`sticky left-0 px-2 ${currentDensity.cell} z-10 ${bordered ? `border ${borderColor}` : ''}`}
1060
+ style={{ backgroundColor: 'inherit', verticalAlign: 'middle' }}
1061
+ rowSpan={hasSecondaryRow ? 2 : 1}
1062
+ >
1027
1063
  <button
1028
1064
  onClick={() => {
1029
1065
  // NEW: Enhanced logic for expandedRowConfig
@@ -1059,14 +1095,14 @@ export default function DataTable<T extends BaseDataItem = BaseDataItem>({
1059
1095
  verticalAlign: 'middle'
1060
1096
  }}
1061
1097
  onClick={(e) => e.stopPropagation()}
1062
- rowSpan={visibleColumns.some(col => !!col.renderSecondary) ? 2 : 1}
1098
+ rowSpan={hasSecondaryRow ? 2 : 1}
1063
1099
  >
1064
1100
  <div style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: '28px' }}>
1065
1101
  <ActionMenu actions={allActions} item={item} />
1066
1102
  </div>
1067
1103
  </td>
1068
1104
  )}
1069
- {visibleColumns.map((column) => {
1105
+ {visibleColumns.map((column, colIdx) => {
1070
1106
  const columnKey = String(column.key);
1071
1107
  const dynamicWidth = columnWidths[columnKey];
1072
1108
  const value = typeof column.key === 'string'
@@ -1075,10 +1111,14 @@ export default function DataTable<T extends BaseDataItem = BaseDataItem>({
1075
1111
 
1076
1112
  const primaryContent = column.render ? column.render(item, value) : String(value || '');
1077
1113
 
1114
+ // Reduce left padding on first column when there are action buttons
1115
+ const isFirstColumn = colIdx === 0;
1116
+ const paddingClass = isFirstColumn && allActions.length > 0 ? 'pl-3' : '';
1117
+
1078
1118
  return (
1079
1119
  <td
1080
1120
  key={`${item.id}-${columnKey}`}
1081
- className={`${currentDensity.cell} ${column.className || ''} ${bordered ? `border ${borderColor}` : ''}`}
1121
+ className={`${currentDensity.cell} ${paddingClass} ${column.className || ''} ${bordered ? `border ${borderColor}` : ''}`}
1082
1122
  style={getColumnStyle(column, dynamicWidth)}
1083
1123
  >
1084
1124
  <div className={`${currentDensity.text} leading-tight`}>{primaryContent}</div>
@@ -1088,12 +1128,16 @@ export default function DataTable<T extends BaseDataItem = BaseDataItem>({
1088
1128
  </tr>
1089
1129
 
1090
1130
  {/* Secondary row - only render if any column has renderSecondary */}
1091
- {visibleColumns.some(col => !!col.renderSecondary) && (
1092
- <tr className={`secondary-row ${hoverClass} border-b ${borderColor}`}>
1093
- {selectable && <td className={`sticky left-0 bg-white ${currentDensity.cell} py-0.5 z-10 ${bordered ? `border ${borderColor}` : ''}`}></td>}
1094
- {((expandable || expandedRowConfig) && showExpandChevron) && <td className={`sticky left-0 bg-white px-2 py-0.5 z-10 ${bordered ? `border ${borderColor}` : ''}`}></td>}
1131
+ {hasSecondaryRow && (
1132
+ <tr
1133
+ className={`secondary-row ${isSelected ? 'bg-accent-50 border-l-2 border-accent-500' : hoverClass || rowBgClass} border-b ${borderColor}`}
1134
+ onMouseEnter={() => !disableHover && setHoveredRowKey(rowKey)}
1135
+ onMouseLeave={() => !disableHover && setHoveredRowKey(null)}
1136
+ >
1137
+ {/* Selectable checkbox uses rowspan from primary row, no cell needed here */}
1138
+ {/* Expand chevron uses rowspan from primary row, no cell needed here */}
1095
1139
  {/* Actions column uses rowspan from primary row, no cell needed here */}
1096
- {visibleColumns.map((column) => {
1140
+ {visibleColumns.map((column, colIdx) => {
1097
1141
  const columnKey = String(column.key);
1098
1142
  const dynamicWidth = columnWidths[columnKey];
1099
1143
  const value = typeof column.key === 'string'
@@ -1101,10 +1145,14 @@ export default function DataTable<T extends BaseDataItem = BaseDataItem>({
1101
1145
  : item[column.key];
1102
1146
  const secondaryContent = column.renderSecondary ? column.renderSecondary(item, value) : null;
1103
1147
 
1148
+ // Reduce left padding on first column when there are action buttons
1149
+ const isFirstColumn = colIdx === 0;
1150
+ const paddingClass = isFirstColumn && allActions.length > 0 ? 'pl-3' : '';
1151
+
1104
1152
  return (
1105
1153
  <td
1106
1154
  key={`${item.id}-${columnKey}-secondary`}
1107
- className={`${currentDensity.cell} py-0.5 ${column.className || ''} ${bordered ? `border ${borderColor}` : ''}`}
1155
+ className={`${currentDensity.cell} py-0.5 ${paddingClass} ${column.className || ''} ${bordered ? `border ${borderColor}` : ''}`}
1108
1156
  style={getColumnStyle(column, dynamicWidth)}
1109
1157
  >
1110
1158
  <div className="text-xs text-ink-500 leading-tight">
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Spreadsheet Component Styles
3
+ *
4
+ * Custom styling for react-spreadsheet to match notebook-ui's paper aesthetic
5
+ */
6
+
7
+ /* Container */
8
+ .spreadsheet-container {
9
+ width: 100%;
10
+ overflow: auto;
11
+ background-color: #fafaf9; /* paper-50 */
12
+ border-radius: 0.5rem;
13
+ border: 1px solid #e7e5e4; /* stone-200 */
14
+ }
15
+
16
+ /* Spreadsheet base */
17
+ .notebook-spreadsheet {
18
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
19
+ font-size: 0.875rem;
20
+ color: #1c1917; /* ink-900 */
21
+ }
22
+
23
+ /* Table styling */
24
+ .notebook-spreadsheet table {
25
+ border-collapse: separate;
26
+ border-spacing: 0;
27
+ background-color: #ffffff;
28
+ width: 100%;
29
+ }
30
+
31
+ /* Cell styling */
32
+ .notebook-spreadsheet td {
33
+ border: 1px solid #e7e5e4; /* stone-200 */
34
+ padding: 0;
35
+ background-color: #ffffff;
36
+ transition: background-color 0.15s ease;
37
+ }
38
+
39
+ /* Cell hover */
40
+ .notebook-spreadsheet td:hover {
41
+ background-color: #fafaf9; /* paper-50 */
42
+ }
43
+
44
+ /* Selected cell */
45
+ .notebook-spreadsheet td.Spreadsheet__active-cell {
46
+ border: 2px solid #334155; /* primary-700 */
47
+ box-shadow: 0 0 0 1px #334155;
48
+ background-color: #ffffff;
49
+ z-index: 10;
50
+ }
51
+
52
+ /* Header cells (row/column labels) */
53
+ .notebook-spreadsheet th {
54
+ background-color: #f5f5f4; /* stone-100 */
55
+ color: #57534e; /* ink-600 */
56
+ border: 1px solid #e7e5e4; /* stone-200 */
57
+ padding: 0.5rem;
58
+ font-weight: 600;
59
+ font-size: 0.75rem;
60
+ text-align: center;
61
+ position: sticky;
62
+ z-index: 5;
63
+ }
64
+
65
+ /* Column headers */
66
+ .notebook-spreadsheet thead th {
67
+ top: 0;
68
+ z-index: 10;
69
+ }
70
+
71
+ /* Row headers */
72
+ .notebook-spreadsheet tbody th {
73
+ left: 0;
74
+ z-index: 5;
75
+ }
76
+
77
+ /* Corner header (top-left cell) */
78
+ .notebook-spreadsheet thead th:first-child {
79
+ left: 0;
80
+ z-index: 15;
81
+ }
82
+
83
+ /* Cell input */
84
+ .notebook-spreadsheet .Spreadsheet__data-editor {
85
+ width: 100%;
86
+ height: 100%;
87
+ border: none;
88
+ outline: none;
89
+ padding: 0.5rem;
90
+ font-family: inherit;
91
+ font-size: inherit;
92
+ color: inherit;
93
+ background-color: #ffffff;
94
+ box-sizing: border-box;
95
+ }
96
+
97
+ .notebook-spreadsheet .Spreadsheet__data-editor:focus {
98
+ background-color: #ffffff;
99
+ border: 2px solid #334155; /* primary-700 */
100
+ padding: calc(0.5rem - 1px);
101
+ }
102
+
103
+ /* Cell with formula indicator */
104
+ .notebook-spreadsheet .Spreadsheet__cell--formula {
105
+ font-style: italic;
106
+ background-color: #f0fdf4; /* success-50 */
107
+ }
108
+
109
+ /* Read-only cells */
110
+ .notebook-spreadsheet .Spreadsheet__cell--readonly {
111
+ background-color: #f5f5f4; /* stone-100 */
112
+ color: #78716c; /* ink-500 */
113
+ }
114
+
115
+ /* Selection highlight */
116
+ .notebook-spreadsheet .Spreadsheet__cell--selected {
117
+ background-color: #e0f2fe; /* primary-100 */
118
+ }
119
+
120
+ /* Cell error state */
121
+ .notebook-spreadsheet .Spreadsheet__cell--error {
122
+ background-color: #fef2f2; /* error-50 */
123
+ color: #991b1b; /* error-800 */
124
+ }
125
+
126
+ /* Cell value display */
127
+ .notebook-spreadsheet .Spreadsheet__value {
128
+ padding: 0.5rem;
129
+ min-height: 2rem;
130
+ display: flex;
131
+ align-items: center;
132
+ }
133
+
134
+ /* Number cells - align right */
135
+ .notebook-spreadsheet .Spreadsheet__cell--number .Spreadsheet__value {
136
+ justify-content: flex-end;
137
+ font-variant-numeric: tabular-nums;
138
+ }
139
+
140
+ /* Empty cells */
141
+ .notebook-spreadsheet .Spreadsheet__cell--empty .Spreadsheet__value {
142
+ color: #a8a29e; /* ink-400 */
143
+ }
144
+
145
+ /* Copy/paste indicator */
146
+ .notebook-spreadsheet .Spreadsheet__floating-rect {
147
+ border: 2px dashed #334155; /* primary-700 */
148
+ background-color: rgba(51, 65, 85, 0.1);
149
+ pointer-events: none;
150
+ }
151
+
152
+ /* Scrollbar styling for webkit browsers */
153
+ .spreadsheet-container::-webkit-scrollbar {
154
+ width: 12px;
155
+ height: 12px;
156
+ }
157
+
158
+ .spreadsheet-container::-webkit-scrollbar-track {
159
+ background-color: #fafaf9; /* paper-50 */
160
+ border-radius: 0.5rem;
161
+ }
162
+
163
+ .spreadsheet-container::-webkit-scrollbar-thumb {
164
+ background-color: #d6d3d1; /* stone-300 */
165
+ border-radius: 0.5rem;
166
+ border: 2px solid #fafaf9;
167
+ }
168
+
169
+ .spreadsheet-container::-webkit-scrollbar-thumb:hover {
170
+ background-color: #a8a29e; /* ink-400 */
171
+ }
172
+
173
+ /* Loading state */
174
+ .spreadsheet-container.loading {
175
+ opacity: 0.6;
176
+ pointer-events: none;
177
+ }
178
+
179
+ /* Responsive adjustments */
180
+ @media (max-width: 768px) {
181
+ .notebook-spreadsheet {
182
+ font-size: 0.75rem;
183
+ }
184
+
185
+ .notebook-spreadsheet .Spreadsheet__value {
186
+ padding: 0.375rem;
187
+ min-height: 1.75rem;
188
+ }
189
+
190
+ .notebook-spreadsheet .Spreadsheet__data-editor {
191
+ padding: 0.375rem;
192
+ }
193
+
194
+ .notebook-spreadsheet th {
195
+ padding: 0.375rem;
196
+ font-size: 0.6875rem;
197
+ }
198
+ }
199
+
200
+ /* Print styles */
201
+ @media print {
202
+ .spreadsheet-container {
203
+ border: none;
204
+ overflow: visible;
205
+ }
206
+
207
+ .notebook-spreadsheet td,
208
+ .notebook-spreadsheet th {
209
+ border-color: #000;
210
+ }
211
+
212
+ .notebook-spreadsheet .Spreadsheet__active-cell {
213
+ border: 1px solid #000;
214
+ box-shadow: none;
215
+ }
216
+ }