@quadrats/react 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/card/components/Card.js +83 -75
- package/card/index.cjs.js +82 -74
- package/carousel/components/Carousel.js +32 -28
- package/carousel/index.cjs.js +32 -28
- package/components/Tooltip/index.js +5 -2
- package/components/index.cjs.js +5 -2
- package/embed/renderers/base/components/BaseEmbedElement.js +51 -43
- package/embed/renderers/base/index.cjs.js +50 -42
- package/image/components/Image.js +34 -26
- package/image/createReactImage.js +1 -1
- package/image/index.cjs.js +34 -26
- package/package.json +4 -4
- package/table/components/Table.d.ts +9 -0
- package/table/components/Table.js +231 -0
- package/table/components/TableBody.d.ts +5 -0
- package/table/components/TableBody.js +8 -0
- package/table/components/TableCell.d.ts +5 -0
- package/table/components/TableCell.js +191 -0
- package/table/components/TableHeader.d.ts +5 -0
- package/table/components/TableHeader.js +13 -0
- package/table/components/TableMain.d.ts +5 -0
- package/table/components/TableMain.js +225 -0
- package/table/components/TableRow.d.ts +5 -0
- package/table/components/TableRow.js +8 -0
- package/table/components/TableTitle.d.ts +5 -0
- package/table/components/TableTitle.js +18 -0
- package/table/contexts/TableActionsContext.d.ts +3 -0
- package/table/contexts/TableActionsContext.js +5 -0
- package/table/contexts/TableHeaderContext.d.ts +2 -0
- package/table/contexts/TableHeaderContext.js +7 -0
- package/table/contexts/TableMetadataContext.d.ts +3 -0
- package/table/contexts/TableMetadataContext.js +5 -0
- package/table/contexts/TableScrollContext.d.ts +2 -0
- package/table/contexts/TableScrollContext.js +9 -0
- package/table/contexts/TableStateContext.d.ts +3 -0
- package/table/contexts/TableStateContext.js +5 -0
- package/table/createReactTable.d.ts +4 -0
- package/table/createReactTable.js +297 -0
- package/table/defaultRenderTableElements.d.ts +2 -0
- package/table/defaultRenderTableElements.js +20 -0
- package/table/hooks/useColumnResize.d.ts +12 -0
- package/table/hooks/useColumnResize.js +139 -0
- package/table/hooks/useTableActions.d.ts +25 -0
- package/table/hooks/useTableActions.js +886 -0
- package/table/hooks/useTableActionsContext.d.ts +1 -0
- package/table/hooks/useTableActionsContext.js +12 -0
- package/table/hooks/useTableCell.d.ts +16 -0
- package/table/hooks/useTableCell.js +166 -0
- package/table/hooks/useTableCellToolbarActions.d.ts +34 -0
- package/table/hooks/useTableCellToolbarActions.js +404 -0
- package/table/hooks/useTableMetadata.d.ts +1 -0
- package/table/hooks/useTableMetadata.js +12 -0
- package/table/hooks/useTableStateContext.d.ts +1 -0
- package/table/hooks/useTableStateContext.js +12 -0
- package/table/hooks/useTableStates.d.ts +18 -0
- package/table/hooks/useTableStates.js +14 -0
- package/table/index.cjs.js +3254 -0
- package/table/index.d.ts +16 -0
- package/table/index.js +24 -0
- package/table/jsx-serializer/components/Table.d.ts +3 -0
- package/table/jsx-serializer/components/Table.js +7 -0
- package/table/jsx-serializer/components/TableBody.d.ts +3 -0
- package/table/jsx-serializer/components/TableBody.js +7 -0
- package/table/jsx-serializer/components/TableCell.d.ts +5 -0
- package/table/jsx-serializer/components/TableCell.js +33 -0
- package/table/jsx-serializer/components/TableHeader.d.ts +3 -0
- package/table/jsx-serializer/components/TableHeader.js +10 -0
- package/table/jsx-serializer/components/TableMain.d.ts +6 -0
- package/table/jsx-serializer/components/TableMain.js +18 -0
- package/table/jsx-serializer/components/TableRow.d.ts +3 -0
- package/table/jsx-serializer/components/TableRow.js +7 -0
- package/table/jsx-serializer/components/TableTitle.d.ts +3 -0
- package/table/jsx-serializer/components/TableTitle.js +7 -0
- package/table/jsx-serializer/contexts/TableHeaderContext.d.ts +1 -0
- package/table/jsx-serializer/contexts/TableHeaderContext.js +5 -0
- package/table/jsx-serializer/contexts/TableScrollContext.d.ts +2 -0
- package/table/jsx-serializer/contexts/TableScrollContext.js +7 -0
- package/table/jsx-serializer/createJsxSerializeTable.d.ts +5 -0
- package/table/jsx-serializer/createJsxSerializeTable.js +113 -0
- package/table/jsx-serializer/defaultRenderTableElements.d.ts +2 -0
- package/table/jsx-serializer/defaultRenderTableElements.js +20 -0
- package/table/jsx-serializer/index.cjs.js +195 -0
- package/table/jsx-serializer/index.d.ts +3 -0
- package/table/jsx-serializer/index.js +2 -0
- package/table/jsx-serializer/package.json +7 -0
- package/table/jsx-serializer/typings.d.ts +12 -0
- package/table/package.json +10 -0
- package/table/table.css +1 -0
- package/table/table.scss +393 -0
- package/table/toolbar/TableToolbarIcon.d.ts +8 -0
- package/table/toolbar/TableToolbarIcon.js +12 -0
- package/table/toolbar/index.cjs.js +24 -0
- package/table/toolbar/index.d.ts +2 -0
- package/table/toolbar/index.js +2 -0
- package/table/toolbar/package.json +7 -0
- package/table/toolbar/useTableTool.d.ts +4 -0
- package/table/toolbar/useTableTool.js +13 -0
- package/table/typings.d.ts +66 -0
- package/table/utils/helper.d.ts +160 -0
- package/table/utils/helper.js +693 -0
- package/toolbar/components/InlineToolbar.d.ts +12 -11
- package/toolbar/components/InlineToolbar.js +23 -19
- package/toolbar/components/Toolbar.js +2 -2
- package/toolbar/index.cjs.js +24 -21
- package/toolbar/toolbar.css +1 -1
- package/toolbar/toolbar.scss +4 -1
- package/utils/index.cjs.js +7 -1
- package/utils/removePreviousElement.js +7 -1
package/table/table.scss
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
$cell-action-z-index: 9;
|
|
2
|
+
$toolbar-z-index: 10;
|
|
3
|
+
|
|
4
|
+
@mixin add-btn {
|
|
5
|
+
position: absolute;
|
|
6
|
+
z-index: 0;
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
padding: 0;
|
|
9
|
+
background-color: var(--qdr-block);
|
|
10
|
+
border-radius: var(--qdr-radius-1);
|
|
11
|
+
border: 1px solid var(--qdr-divider);
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
|
|
16
|
+
&:hover {
|
|
17
|
+
background-color: var(--qdr-bg);
|
|
18
|
+
|
|
19
|
+
.qdr-table__btn-icon {
|
|
20
|
+
color: var(--qdr-text-secondary);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&:active {
|
|
25
|
+
background-color: var(--qdr-divider);
|
|
26
|
+
border: 1px solid var(--qdr-border);
|
|
27
|
+
|
|
28
|
+
.qdr-table__btn-icon {
|
|
29
|
+
color: var(--qdr-text-secondary);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@mixin cell-action {
|
|
35
|
+
position: absolute;
|
|
36
|
+
z-index: $cell-action-z-index;
|
|
37
|
+
width: 20px;
|
|
38
|
+
height: 24px;
|
|
39
|
+
padding: 0;
|
|
40
|
+
border-radius: var(--qdr-radius-1);
|
|
41
|
+
border: 1px solid var(--qdr-primary-active-bg);
|
|
42
|
+
background-color: var(--qdr-primary-hover-bg);
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
pointer-events: auto;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@mixin cell-selected($border-position) {
|
|
52
|
+
border-#{$border-position}: 2px solid var(--qdr-primary-light) !important;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@mixin title-bg {
|
|
56
|
+
background-color: var(--qdr-bg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.qdr-table__table-toolbar {
|
|
60
|
+
right: unset;
|
|
61
|
+
left: 50%;
|
|
62
|
+
top: -4px;
|
|
63
|
+
transform: translate(-50%, -100%);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.qdr-table {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-flow: column;
|
|
69
|
+
align-items: flex-start;
|
|
70
|
+
gap: var(--qdr-spacing-4);
|
|
71
|
+
margin: var(--qdr-spacing-11) 0;
|
|
72
|
+
position: relative;
|
|
73
|
+
|
|
74
|
+
&__selection {
|
|
75
|
+
padding: 0;
|
|
76
|
+
position: absolute;
|
|
77
|
+
left: -22px;
|
|
78
|
+
top: 0;
|
|
79
|
+
z-index: 0;
|
|
80
|
+
width: 20px;
|
|
81
|
+
height: 20px;
|
|
82
|
+
color: var(--qdr-action-inactive);
|
|
83
|
+
border: none;
|
|
84
|
+
border-radius: var(--qdr-radius-1);
|
|
85
|
+
background-color: transparent;
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
justify-content: center;
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
|
|
91
|
+
&:hover {
|
|
92
|
+
background-color: var(--qdr-secondary-active-bg);
|
|
93
|
+
color: var(--qdr-action-active);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&__portal-container {
|
|
98
|
+
position: relative;
|
|
99
|
+
pointer-events: none;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
&__title {
|
|
103
|
+
width: 100%;
|
|
104
|
+
display: block;
|
|
105
|
+
position: relative;
|
|
106
|
+
margin: 0;
|
|
107
|
+
font-size: var(--qdr-typography-article-h6-font-size);
|
|
108
|
+
line-height: var(--qdr-typography-article-h6-line-height);
|
|
109
|
+
letter-spacing: var(--qdr-typography-article-h6-letter-spacing);
|
|
110
|
+
font-weight: var(--qdr-typography-article-h6-font-weight);
|
|
111
|
+
color: var(--qdr-text-primary);
|
|
112
|
+
background-color: var(--qdr-surface-secondary);
|
|
113
|
+
|
|
114
|
+
&__placeholder {
|
|
115
|
+
position: absolute;
|
|
116
|
+
left: 0;
|
|
117
|
+
top: 0;
|
|
118
|
+
color: var(--qdr-text-secondary);
|
|
119
|
+
pointer-events: none;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
&__header {
|
|
124
|
+
@include title-bg();
|
|
125
|
+
|
|
126
|
+
&--pinned {
|
|
127
|
+
position: sticky;
|
|
128
|
+
z-index: 2;
|
|
129
|
+
top: 0;
|
|
130
|
+
box-shadow: 0 2px 4px -2px #00000026;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&__scrollContainer {
|
|
135
|
+
width: 100%;
|
|
136
|
+
max-width: 100%;
|
|
137
|
+
max-height: 420px;
|
|
138
|
+
overflow: auto;
|
|
139
|
+
scrollbar-width: thin;
|
|
140
|
+
position: relative;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
&__main {
|
|
144
|
+
margin: 0;
|
|
145
|
+
border-collapse: separate;
|
|
146
|
+
border-spacing: 0;
|
|
147
|
+
table-layout: fixed;
|
|
148
|
+
|
|
149
|
+
th:not(:first-child),
|
|
150
|
+
td:not(:first-child) {
|
|
151
|
+
border-left: none;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
thead tr:not(:last-child) th,
|
|
155
|
+
tbody tr:not(:last-child) td {
|
|
156
|
+
border-bottom: none;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
&__inline-table-toolbar,
|
|
161
|
+
&__cell__inline-table-toolbar {
|
|
162
|
+
pointer-events: none;
|
|
163
|
+
top: -50px;
|
|
164
|
+
left: 0;
|
|
165
|
+
right: unset;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
&__mainWrapper {
|
|
169
|
+
width: 100%;
|
|
170
|
+
max-width: 100%;
|
|
171
|
+
height: 100%;
|
|
172
|
+
position: relative;
|
|
173
|
+
|
|
174
|
+
&--selected {
|
|
175
|
+
.qdr-table__main {
|
|
176
|
+
border: 2px solid var(--qdr-primary);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.qdr-table__table-toolbar {
|
|
180
|
+
opacity: 1;
|
|
181
|
+
pointer-events: auto;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
&__body {
|
|
187
|
+
background-color: var(--qdr-surface-primary);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
&__cell {
|
|
191
|
+
position: relative;
|
|
192
|
+
padding: var(--qdr-spacing-3) var(--qdr-spacing-4);
|
|
193
|
+
font-size: var(--qdr-typography-article-body1-font-size);
|
|
194
|
+
line-height: var(--qdr-typography-article-body1-line-height);
|
|
195
|
+
letter-spacing: var(--qdr-typography-article-body1-letter-spacing);
|
|
196
|
+
font-weight: var(--qdr-typography-article-body1-font-weight);
|
|
197
|
+
color: var(--qdr-text-primary);
|
|
198
|
+
text-align: left;
|
|
199
|
+
border-top: 1px solid var(--qdr-border);
|
|
200
|
+
border-right: 1px solid var(--qdr-border);
|
|
201
|
+
border-bottom: 1px solid var(--qdr-border);
|
|
202
|
+
border-left: 1px solid var(--qdr-border);
|
|
203
|
+
vertical-align: top;
|
|
204
|
+
word-break: break-all;
|
|
205
|
+
|
|
206
|
+
p,
|
|
207
|
+
ul,
|
|
208
|
+
ol {
|
|
209
|
+
margin: 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
&--resizing {
|
|
213
|
+
&::after {
|
|
214
|
+
content: '';
|
|
215
|
+
position: absolute;
|
|
216
|
+
right: 0;
|
|
217
|
+
top: 0;
|
|
218
|
+
width: 2px;
|
|
219
|
+
height: 100%;
|
|
220
|
+
background-color: var(--qdr-primary-light);
|
|
221
|
+
pointer-events: none;
|
|
222
|
+
opacity: 1;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
&__resize-handle {
|
|
227
|
+
position: absolute;
|
|
228
|
+
right: 0;
|
|
229
|
+
top: 0;
|
|
230
|
+
width: 6px;
|
|
231
|
+
height: 100%;
|
|
232
|
+
transform: translateX(0);
|
|
233
|
+
cursor: col-resize;
|
|
234
|
+
z-index: 1;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
&--header {
|
|
238
|
+
font-weight: var(--qdr-typography-article-h6-font-weight);
|
|
239
|
+
color: var(--qdr-text-primary);
|
|
240
|
+
@include title-bg();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
&--pinned {
|
|
244
|
+
position: sticky;
|
|
245
|
+
z-index: 1;
|
|
246
|
+
left: 0;
|
|
247
|
+
box-shadow: 2px 0 4px -2px #00000026;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
&--top-active {
|
|
251
|
+
@include cell-selected('top');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
&--right-active {
|
|
255
|
+
@include cell-selected('right');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
&--bottom-active {
|
|
259
|
+
@include cell-selected('bottom');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
&--left-active {
|
|
263
|
+
@include cell-selected('left');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
&__btn-icon {
|
|
268
|
+
color: var(--qdr-action-disabled);
|
|
269
|
+
pointer-events: none;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
&__add-column {
|
|
273
|
+
@include add-btn();
|
|
274
|
+
|
|
275
|
+
right: -24px;
|
|
276
|
+
top: 0;
|
|
277
|
+
width: 20px;
|
|
278
|
+
height: 100%;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
&__add-row {
|
|
282
|
+
@include add-btn();
|
|
283
|
+
|
|
284
|
+
bottom: -24px;
|
|
285
|
+
left: 0;
|
|
286
|
+
width: 100%;
|
|
287
|
+
height: 20px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
&__add-both {
|
|
291
|
+
@include add-btn();
|
|
292
|
+
|
|
293
|
+
right: -24px;
|
|
294
|
+
bottom: -24px;
|
|
295
|
+
width: 20px;
|
|
296
|
+
height: 20px;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
&__delete {
|
|
300
|
+
color: var(--qdr-error);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// 為了解決 toolbar 顯示時,因為位置錯誤而導致的閃爍問題
|
|
305
|
+
// 讓 toolbar 出現時稍晚一些
|
|
306
|
+
@keyframes fade-in {
|
|
307
|
+
0% {
|
|
308
|
+
opacity: 0;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
100% {
|
|
312
|
+
opacity: 1;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.qdr-table__cell__focus-toolbar,
|
|
317
|
+
.qdr-table__cell__inline-table-toolbar {
|
|
318
|
+
position: absolute;
|
|
319
|
+
right: unset;
|
|
320
|
+
transform: translate(-10%, -100%);
|
|
321
|
+
padding: 4px;
|
|
322
|
+
border-radius: 10px;
|
|
323
|
+
border: 1px solid var(--qdr-border);
|
|
324
|
+
background: var(--qdr-bg);
|
|
325
|
+
box-shadow:
|
|
326
|
+
0 4px 8px -2px #0000001a,
|
|
327
|
+
0 2px 4px -2px #0000000a;
|
|
328
|
+
animation-name: fade-in;
|
|
329
|
+
animation-duration: 0.1s;
|
|
330
|
+
animation-delay: 0.1s;
|
|
331
|
+
animation-iteration-count: 1;
|
|
332
|
+
animation-fill-mode: forwards;
|
|
333
|
+
animation-timing-function: linear;
|
|
334
|
+
pointer-events: auto;
|
|
335
|
+
z-index: $toolbar-z-index;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.qdr-table__cell-row-action {
|
|
339
|
+
@include cell-action();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.qdr-table__cell-column-action {
|
|
343
|
+
@include cell-action();
|
|
344
|
+
|
|
345
|
+
transform: rotate(90deg);
|
|
346
|
+
transform-origin: center;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.qdr-table__size-indicators {
|
|
350
|
+
display: none;
|
|
351
|
+
overflow: hidden;
|
|
352
|
+
position: absolute;
|
|
353
|
+
z-index: 1;
|
|
354
|
+
left: 0;
|
|
355
|
+
top: 0;
|
|
356
|
+
width: 100%;
|
|
357
|
+
max-width: 100%;
|
|
358
|
+
padding: 8px 0;
|
|
359
|
+
pointer-events: none;
|
|
360
|
+
transform: translateY(-100%);
|
|
361
|
+
flex-flow: row nowrap;
|
|
362
|
+
align-items: center;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.qdr-table__size-indicator {
|
|
366
|
+
display: flex;
|
|
367
|
+
align-items: center;
|
|
368
|
+
justify-content: center;
|
|
369
|
+
position: relative;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.qdr-table__size {
|
|
373
|
+
background-color: var(--qdr-action-inactive);
|
|
374
|
+
color: var(--qdr-on-primary);
|
|
375
|
+
padding: 4px 8px;
|
|
376
|
+
font-size: 12px;
|
|
377
|
+
white-space: pre-wrap;
|
|
378
|
+
position: relative;
|
|
379
|
+
|
|
380
|
+
&::after {
|
|
381
|
+
position: absolute;
|
|
382
|
+
content: '';
|
|
383
|
+
z-index: -1;
|
|
384
|
+
top: calc(100% - 2px);
|
|
385
|
+
left: 50%;
|
|
386
|
+
width: 10px;
|
|
387
|
+
height: 10px;
|
|
388
|
+
background-color: var(--qdr-action-inactive);
|
|
389
|
+
border-right: 1px solid var(--qdr-action-inactive);
|
|
390
|
+
border-bottom: 1px solid var(--qdr-action-inactive);
|
|
391
|
+
transform: translateX(-50%) translateY(-50%) rotate(45deg);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ToolbarIconProps } from '@quadrats/react/toolbar';
|
|
3
|
+
import { ReactTable } from '@quadrats/react/table';
|
|
4
|
+
export interface TableToolbarIconProps extends Omit<ToolbarIconProps, 'active' | 'onClick'> {
|
|
5
|
+
controller: ReactTable;
|
|
6
|
+
}
|
|
7
|
+
declare function TableToolbarIcon(props: TableToolbarIconProps): React.JSX.Element;
|
|
8
|
+
export default TableToolbarIcon;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { __rest } from 'tslib';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ToolbarIcon } from '@quadrats/react/toolbar';
|
|
4
|
+
import { useTableTool } from './useTableTool.js';
|
|
5
|
+
|
|
6
|
+
function TableToolbarIcon(props) {
|
|
7
|
+
const { controller } = props, rest = __rest(props, ["controller"]);
|
|
8
|
+
const { insert } = useTableTool(controller);
|
|
9
|
+
return React.createElement(ToolbarIcon, Object.assign({}, rest, { onClick: insert }));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { TableToolbarIcon as default };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var react = require('@quadrats/react');
|
|
5
|
+
var tslib = require('tslib');
|
|
6
|
+
var toolbar = require('@quadrats/react/toolbar');
|
|
7
|
+
|
|
8
|
+
function useTableTool(table) {
|
|
9
|
+
const editor = react.useQuadrats();
|
|
10
|
+
const insert = React.useCallback(() => {
|
|
11
|
+
// Insert a 3x3 table
|
|
12
|
+
table.insertTable(editor, 3, 3);
|
|
13
|
+
}, [editor, table]);
|
|
14
|
+
return { insert };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function TableToolbarIcon(props) {
|
|
18
|
+
const { controller } = props, rest = tslib.__rest(props, ["controller"]);
|
|
19
|
+
const { insert } = useTableTool(controller);
|
|
20
|
+
return React.createElement(toolbar.ToolbarIcon, Object.assign({}, rest, { onClick: insert }));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.TableToolbarIcon = TableToolbarIcon;
|
|
24
|
+
exports.useTableTool = useTableTool;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useQuadrats } from '@quadrats/react';
|
|
3
|
+
|
|
4
|
+
function useTableTool(table) {
|
|
5
|
+
const editor = useQuadrats();
|
|
6
|
+
const insert = useCallback(() => {
|
|
7
|
+
// Insert a 3x3 table
|
|
8
|
+
table.insertTable(editor, 3, 3);
|
|
9
|
+
}, [editor, table]);
|
|
10
|
+
return { insert };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { useTableTool };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Editor } from '@quadrats/core';
|
|
2
|
+
import { Table, TableElement, TableTypeKey, TableTitleTypeKey, TableMainTypeKey, TableHeaderTypeKey, TableRowTypeKey, TableCellTypeKey, TableBodyTypeKey } from '@quadrats/common/table';
|
|
3
|
+
import { WithCreateHandlers, WithCreateRenderElement, RenderElementProps, ReactWithable } from '@quadrats/react';
|
|
4
|
+
import { Dispatch, SetStateAction, RefObject } from 'react';
|
|
5
|
+
export type TableHeaderContextType = {
|
|
6
|
+
isHeader: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type TableContextType = {
|
|
9
|
+
tableElement: TableElement;
|
|
10
|
+
columnCount: number;
|
|
11
|
+
rowCount: number;
|
|
12
|
+
portalContainerRef: RefObject<HTMLDivElement | null>;
|
|
13
|
+
pinnedColumns: Set<number>;
|
|
14
|
+
pinnedRows: Set<number>;
|
|
15
|
+
cellPositions: Map<TableElement, {
|
|
16
|
+
columnIndex: number;
|
|
17
|
+
rowIndex: number;
|
|
18
|
+
}>;
|
|
19
|
+
addColumn: (options?: {
|
|
20
|
+
position?: 'left' | 'right';
|
|
21
|
+
columnIndex?: number;
|
|
22
|
+
}) => void;
|
|
23
|
+
addRow: (options?: {
|
|
24
|
+
position?: 'top' | 'bottom';
|
|
25
|
+
rowIndex?: number;
|
|
26
|
+
}) => void;
|
|
27
|
+
addColumnAndRow: VoidFunction;
|
|
28
|
+
deleteRow: (rowIndex: number) => void;
|
|
29
|
+
deleteColumn: (columnIndex: number) => void;
|
|
30
|
+
moveRowToBody: (rowIndex: number) => void;
|
|
31
|
+
moveRowToHeader: (rowIndex: number, customProps?: Pick<TableElement, 'pinned'>) => void;
|
|
32
|
+
unsetColumnAsTitle: (columnIndex: number) => void;
|
|
33
|
+
setColumnAsTitle: (columnIndex: number, customProps?: Pick<TableElement, 'pinned'>) => void;
|
|
34
|
+
pinColumn: (columnIndex: number) => void;
|
|
35
|
+
unpinColumn: () => void;
|
|
36
|
+
pinRow: (rowIndex: number) => void;
|
|
37
|
+
unpinRow: () => void;
|
|
38
|
+
isColumnPinned: (columnIndex: number) => boolean;
|
|
39
|
+
isRowPinned: (rowIndex: number) => boolean;
|
|
40
|
+
isReachMaximumColumns: boolean;
|
|
41
|
+
isReachMaximumRows: boolean;
|
|
42
|
+
isReachMinimumNormalColumns: boolean;
|
|
43
|
+
isReachMinimumBodyRows: boolean;
|
|
44
|
+
tableSelectedOn: {
|
|
45
|
+
region: 'table' | 'header' | 'row' | 'column';
|
|
46
|
+
index?: number;
|
|
47
|
+
} | undefined;
|
|
48
|
+
setTableSelectedOn: Dispatch<SetStateAction<TableContextType['tableSelectedOn']>>;
|
|
49
|
+
tableHoveredOn: {
|
|
50
|
+
columnIndex: number;
|
|
51
|
+
rowIndex: number;
|
|
52
|
+
} | undefined;
|
|
53
|
+
setTableHoveredOn: Dispatch<SetStateAction<TableContextType['tableHoveredOn']>>;
|
|
54
|
+
};
|
|
55
|
+
export type TableScrollContextType = {
|
|
56
|
+
scrollRef: RefObject<HTMLDivElement | null>;
|
|
57
|
+
scrollTop: number;
|
|
58
|
+
scrollLeft: number;
|
|
59
|
+
};
|
|
60
|
+
export type RenderTableElementProps = RenderElementProps<TableElement>;
|
|
61
|
+
export type TableRenderElements = Record<TableTypeKey, (props: RenderElementProps<TableElement>) => JSX.Element | null | undefined> & Record<TableTitleTypeKey, (props: RenderElementProps<TableElement>) => JSX.Element | null | undefined> & Record<TableMainTypeKey, (props: RenderElementProps<TableElement>) => JSX.Element | null | undefined> & Record<TableHeaderTypeKey, (props: RenderElementProps<TableElement>) => JSX.Element | null | undefined> & Record<TableBodyTypeKey, (props: RenderElementProps<TableElement>) => JSX.Element | null | undefined> & Record<TableRowTypeKey, (props: RenderElementProps<TableElement>) => JSX.Element | null | undefined> & Record<TableCellTypeKey, (props: RenderElementProps<TableElement>) => JSX.Element | null | undefined>;
|
|
62
|
+
export type ReactTableCreateRenderElementOptions = {
|
|
63
|
+
[K in TableTypeKey | TableTitleTypeKey | TableMainTypeKey | TableHeaderTypeKey | TableBodyTypeKey | TableRowTypeKey | TableCellTypeKey]?: TableRenderElements[K];
|
|
64
|
+
};
|
|
65
|
+
export interface ReactTable extends Omit<Table<Editor>, 'with'>, WithCreateHandlers, WithCreateRenderElement<[ReactTableCreateRenderElementOptions?]>, ReactWithable {
|
|
66
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Element } from '@quadrats/core';
|
|
2
|
+
import { TableElement, ColumnWidth } from '@quadrats/common/table';
|
|
3
|
+
import { QuadratsReactEditor } from '@quadrats/react';
|
|
4
|
+
import { AlignValue } from '@quadrats/common/align';
|
|
5
|
+
export interface TableElements {
|
|
6
|
+
tableMainElement: TableElement | null;
|
|
7
|
+
tableBodyElement: TableElement | null;
|
|
8
|
+
tableHeaderElement: TableElement | null;
|
|
9
|
+
}
|
|
10
|
+
export interface TablePaths {
|
|
11
|
+
tableMainPath: number[];
|
|
12
|
+
tableBodyPath: number[];
|
|
13
|
+
tableHeaderPath: number[] | null;
|
|
14
|
+
}
|
|
15
|
+
export interface TableStructure extends TableElements, TablePaths {
|
|
16
|
+
headerRowCount: number;
|
|
17
|
+
columnCount: number;
|
|
18
|
+
firstRow: Element | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 提取表格的所有基本元素
|
|
22
|
+
*/
|
|
23
|
+
export declare function getTableElements(element: TableElement): TableElements;
|
|
24
|
+
/**
|
|
25
|
+
* 獲取表格的完整結構
|
|
26
|
+
*/
|
|
27
|
+
export declare function getTableStructure(editor: QuadratsReactEditor, element: TableElement): TableStructure | null;
|
|
28
|
+
/**
|
|
29
|
+
* 檢查列是否有 pinned cells
|
|
30
|
+
*/
|
|
31
|
+
export declare function hasColumnPinnedCells(tableStructure: TableStructure, columnIndex: number): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* 檢查是否有任何 pinned columns
|
|
34
|
+
*/
|
|
35
|
+
export declare function hasAnyPinnedColumns(tableStructure: TableStructure): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* 檢查是否有任何 pinned rows
|
|
38
|
+
*/
|
|
39
|
+
export declare function hasAnyPinnedRows(tableStructure: TableStructure): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* 創建新的 table cell
|
|
42
|
+
*/
|
|
43
|
+
export declare function createTableCell(referenceCell?: TableElement, overrideProps?: Partial<TableElement>): TableElement;
|
|
44
|
+
/**
|
|
45
|
+
* 獲取參考 row
|
|
46
|
+
*/
|
|
47
|
+
export declare function getReferenceRowFromHeaderOrBody(HeaderOrBodyContainer: TableElement, rowIndex: number): TableElement | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* 收集指定範圍的 cells
|
|
50
|
+
* @param tableStructure - 表格結構
|
|
51
|
+
* @param scope - 'table' | 'column'
|
|
52
|
+
* @param columnIndex - 當 scope 為 'column' 時需要指定
|
|
53
|
+
* @returns cells 陣列
|
|
54
|
+
*/
|
|
55
|
+
export declare function collectCells(tableStructure: TableStructure, scope: 'table' | 'column', columnIndex?: number): Element[];
|
|
56
|
+
/**
|
|
57
|
+
* 設定指定 cells 的 align
|
|
58
|
+
* @param editor - Slate editor
|
|
59
|
+
* @param cells - 要設定 align 的 cell 元素陣列
|
|
60
|
+
* @param alignValue - align 值
|
|
61
|
+
*/
|
|
62
|
+
export declare function setAlignForCells(editor: QuadratsReactEditor, cells: Element[], alignValue: AlignValue): void;
|
|
63
|
+
/**
|
|
64
|
+
* 獲取指定 cells 的 align 狀態
|
|
65
|
+
* @param cells - 要檢查的 cell 元素陣列
|
|
66
|
+
* @returns 如果所有 cell 的 align 都相同則返回該值,否則返回 'left'
|
|
67
|
+
*/
|
|
68
|
+
export declare function getAlignFromCells(cells: Element[]): AlignValue;
|
|
69
|
+
/**
|
|
70
|
+
* 獲取釘選欄位的資訊
|
|
71
|
+
* @param tableElement - 表格最外層元素
|
|
72
|
+
* @returns 釘選欄位的索引陣列和總寬度百分比
|
|
73
|
+
*/
|
|
74
|
+
export declare function getPinnedColumnsInfo(tableElement: TableElement): {
|
|
75
|
+
pinnedColumnIndices: number[];
|
|
76
|
+
totalPinnedPercentage: number;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* 強制調整釘選欄位寬度以符合最大限制
|
|
80
|
+
* @param columnWidths - 當前欄位寬度陣列
|
|
81
|
+
* @param pinnedColumnIndices - 釘選欄位索引陣列
|
|
82
|
+
* @returns 調整後的欄位寬度陣列
|
|
83
|
+
*/
|
|
84
|
+
export declare function enforcePinnedColumnsMaxWidth(columnWidths: ColumnWidth[], pinnedColumnIndices: number[]): ColumnWidth[];
|
|
85
|
+
/**
|
|
86
|
+
* 獲取表格的欄位寬度陣列
|
|
87
|
+
* 當有釘選欄位時:
|
|
88
|
+
* - 釘選欄位使用 percentage
|
|
89
|
+
* - 未釘選欄位使用 pixel(基於剩餘空間平均分配)
|
|
90
|
+
* @param tableElement - 表格最外層元素
|
|
91
|
+
* @param tableWidth - 表格容器的實際寬度(pixel),用於計算 pixel 寬度
|
|
92
|
+
* @returns 欄位寬度陣列
|
|
93
|
+
*/
|
|
94
|
+
export declare function getColumnWidths(tableElement: TableElement, tableWidth?: number): ColumnWidth[];
|
|
95
|
+
/**
|
|
96
|
+
* 設定表格的欄位寬度
|
|
97
|
+
* @param editor - Slate editor
|
|
98
|
+
* @param tableElement - 表格最外層元素
|
|
99
|
+
* @param columnWidths - 欄位寬度陣列
|
|
100
|
+
*/
|
|
101
|
+
export declare function setColumnWidths(editor: QuadratsReactEditor, tableElement: TableElement, columnWidths: ColumnWidth[]): void;
|
|
102
|
+
/**
|
|
103
|
+
* 計算新增欄位後的欄位寬度
|
|
104
|
+
* - 如果所有欄位都是 percentage:按比例縮減現有欄位,新欄位佔平均寬度
|
|
105
|
+
* - 如果有混合模式(percentage + pixel):
|
|
106
|
+
* * percentage 欄位(pinned)保持不變
|
|
107
|
+
* * 新欄位使用 pixel(與其他 pixel 欄位平均分配剩餘空間)
|
|
108
|
+
*
|
|
109
|
+
* @param currentWidths - 當前的欄位寬度陣列
|
|
110
|
+
* @param insertIndex - 新欄位插入的位置(0-based)
|
|
111
|
+
* @returns 新的欄位寬度陣列
|
|
112
|
+
*/
|
|
113
|
+
export declare function calculateColumnWidthsAfterAdd(currentWidths: ColumnWidth[], insertIndex: number): ColumnWidth[];
|
|
114
|
+
/**
|
|
115
|
+
* 計算刪除欄位後的欄位寬度
|
|
116
|
+
* 此函數會智慧處理欄位寬度的重新分配:
|
|
117
|
+
* - 如果所有欄位都是 percentage:按比例放大剩餘欄位
|
|
118
|
+
* - 如果有 pixel 欄位:保持 pixel 欄位不變,只調整 percentage 欄位
|
|
119
|
+
*
|
|
120
|
+
* @param currentWidths - 當前的欄位寬度陣列
|
|
121
|
+
* @param deleteIndex - 要刪除的欄位索引(0-based)
|
|
122
|
+
* @returns 新的欄位寬度陣列
|
|
123
|
+
*/
|
|
124
|
+
export declare function calculateColumnWidthsAfterDelete(currentWidths: ColumnWidth[], deleteIndex: number): ColumnWidth[];
|
|
125
|
+
/**
|
|
126
|
+
* 計算拖曳後的欄位寬度
|
|
127
|
+
* 處理釘選欄位的特殊邏輯:
|
|
128
|
+
* - 情況 1:未釘選欄位(pixel)與未釘選欄位(pixel)之間:直接改變 pixel 值,允許超出容器
|
|
129
|
+
* - 情況 2:釘選欄位(percentage)與釘選欄位(percentage)之間:互相調整,且總和不超過 40%
|
|
130
|
+
* - 情況 3:釘選欄位(percentage)與未釘選欄位(pixel)之間:
|
|
131
|
+
* * 只調整釘選欄位的百分比(不超過 40% 總限制)
|
|
132
|
+
* * 當 table 未溢出(寬度 < container)時,重新計算所有未釘選欄位的 pixel 值以維持 100%
|
|
133
|
+
* * 當 table 已溢出時,只調整下一個欄位的 pixel 值
|
|
134
|
+
* * 當達到 40% 上限時,停止調整
|
|
135
|
+
* - 預設情況:兩個都是 percentage 但都不是釘選欄位(正常模式)
|
|
136
|
+
*
|
|
137
|
+
* @param currentWidths - 當前的欄位寬度陣列
|
|
138
|
+
* @param columnIndex - 被調整的欄位索引
|
|
139
|
+
* @param deltaPercentage - 寬度變化量(百分比)
|
|
140
|
+
* @param deltaPixel - 寬度變化量(pixel)
|
|
141
|
+
* @param pinnedColumnIndices - 釘選欄位的索引陣列
|
|
142
|
+
* @returns 新的欄位寬度陣列
|
|
143
|
+
*/
|
|
144
|
+
export declare function calculateResizedColumnWidths(currentWidths: ColumnWidth[], columnIndex: number, deltaPercentage: number, deltaPixel: number, pinnedColumnIndices?: number[]): ColumnWidth[];
|
|
145
|
+
/**
|
|
146
|
+
* 移動 columnWidths 陣列中的元素位置
|
|
147
|
+
* @param currentWidths - 當前的欄位寬度陣列
|
|
148
|
+
* @param fromIndex - 來源索引
|
|
149
|
+
* @param toIndex - 目標索引
|
|
150
|
+
* @returns 新的欄位寬度陣列
|
|
151
|
+
*/
|
|
152
|
+
export declare function moveColumnWidth(currentWidths: ColumnWidth[], fromIndex: number, toIndex: number): ColumnWidth[];
|
|
153
|
+
/**
|
|
154
|
+
* 將 columnWidths 轉換為混合模式(釘選欄位用 percentage,未釘選欄位用 pixel)
|
|
155
|
+
* @param currentWidths - 當前的欄位寬度陣列
|
|
156
|
+
* @param pinnedColumnIndices - 釘選欄位的索引陣列
|
|
157
|
+
* @param tableWidth - 表格的實際寬度(pixel)
|
|
158
|
+
* @returns 轉換後的欄位寬度陣列
|
|
159
|
+
*/
|
|
160
|
+
export declare function convertToMixedWidthMode(currentWidths: ColumnWidth[], pinnedColumnIndices: number[], tableWidth: number): ColumnWidth[];
|