@dnax/ui 0.0.67 → 0.0.70
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/components/QChart.vue +552 -27
- package/components/QSpreadsheet.vue +43 -18
- package/index.ts +20 -1
- package/lib/chart.axis.test.ts +1 -1
- package/lib/chart.bi.test.ts +839 -0
- package/lib/chart.modules.test.ts +232 -0
- package/lib/chart.test.ts +13 -4
- package/lib/chart.ts +1451 -80
- package/lib/chartFormat.ts +222 -0
- package/lib/chartStats.ts +178 -0
- package/lib/chartTable.test.ts +140 -0
- package/lib/chartTable.ts +193 -0
- package/lib/history.test.ts +78 -0
- package/lib/history.ts +72 -0
- package/package.json +1 -1
|
@@ -198,6 +198,7 @@ import { checkValidation, type ArkCheck } from "../lib/spreadsheetValidation"
|
|
|
198
198
|
import { normalizeCellOptions } from "../lib/spreadsheetOptions"
|
|
199
199
|
import { inLockRect, lockRects, prefillForRow } from "../lib/spreadsheetZones"
|
|
200
200
|
import { canAddRows, canRemoveRows, clampRows } from "../lib/spreadsheetRows"
|
|
201
|
+
import { createHistory } from "../lib/history"
|
|
201
202
|
import {
|
|
202
203
|
DEFAULT_ROW_KEY,
|
|
203
204
|
diffDocuments,
|
|
@@ -1148,12 +1149,14 @@ const clearCell = (row: number, column: string) => {
|
|
|
1148
1149
|
if (isCellLocked(row, column)) return
|
|
1149
1150
|
const old = state.value[row]?.[column]
|
|
1150
1151
|
if (isBlankValue(old) || (Array.isArray(old) && old.length === 0)) return
|
|
1152
|
+
pushHistory()
|
|
1151
1153
|
setCellValue(row, column, old, null)
|
|
1152
1154
|
}
|
|
1153
1155
|
|
|
1154
1156
|
const toggleBoolean = (row: number, column: string) => {
|
|
1155
1157
|
if (isCellLocked(row, column)) return
|
|
1156
1158
|
const old = !!state.value[row]?.[column]
|
|
1159
|
+
pushHistory()
|
|
1157
1160
|
setCellValue(row, column, old, !old)
|
|
1158
1161
|
}
|
|
1159
1162
|
|
|
@@ -1258,9 +1261,7 @@ interface Snapshot {
|
|
|
1258
1261
|
merges: MergeRange[]
|
|
1259
1262
|
rules: CondRule[]
|
|
1260
1263
|
}
|
|
1261
|
-
const
|
|
1262
|
-
const redoStack: Snapshot[] = []
|
|
1263
|
-
|
|
1264
|
+
const history = createHistory<Snapshot>(100)
|
|
1264
1265
|
const takeSnapshot = (): Snapshot => ({
|
|
1265
1266
|
rows: state.value.map((r) => ({ ...r })),
|
|
1266
1267
|
cols: cols.value.map((c) => ({ ...c })),
|
|
@@ -1273,13 +1274,9 @@ const takeSnapshot = (): Snapshot => ({
|
|
|
1273
1274
|
merges: merges.value.map((m) => ({ ...m })),
|
|
1274
1275
|
rules: condRules.value.map((r) => ({ ...r })),
|
|
1275
1276
|
})
|
|
1276
|
-
const pushHistory = () =>
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
redoStack.length = 0
|
|
1280
|
-
}
|
|
1281
|
-
const canUndo = computed(() => undoStack.length > 0 && !props.readonly && !props.disable)
|
|
1282
|
-
const canRedo = computed(() => redoStack.length > 0 && !props.readonly && !props.disable)
|
|
1277
|
+
const pushHistory = () => history.push(takeSnapshot())
|
|
1278
|
+
const canUndo = computed(() => history.canUndo.value && !props.readonly && !props.disable)
|
|
1279
|
+
const canRedo = computed(() => history.canRedo.value && !props.readonly && !props.disable)
|
|
1283
1280
|
|
|
1284
1281
|
const restoreSnapshot = (s: Snapshot) => {
|
|
1285
1282
|
cols.value = s.cols.map((c) => ({ ...c }))
|
|
@@ -1294,17 +1291,35 @@ const restoreSnapshot = (s: Snapshot) => {
|
|
|
1294
1291
|
condRules.value = s.rules.map((r) => ({ ...r }))
|
|
1295
1292
|
emit("update:columns", cols.value)
|
|
1296
1293
|
pushRows(state.value)
|
|
1294
|
+
// La sélection peut pointer sur une ligne/colonne qui n'existe plus (redo d'une
|
|
1295
|
+
// suppression) : on la ramène sur la première cellule plutôt que de laisser un
|
|
1296
|
+
// curseur fantôme hors grille.
|
|
1297
|
+
const current = sel.value
|
|
1298
|
+
if (current) {
|
|
1299
|
+
const maxRow = state.value.length - 1
|
|
1300
|
+
const bad =
|
|
1301
|
+
colIndex(current.column) === -1 ||
|
|
1302
|
+
(current.endColumn !== undefined && colIndex(current.endColumn) === -1) ||
|
|
1303
|
+
current.row > maxRow ||
|
|
1304
|
+
(current.endRow !== undefined && current.endRow > maxRow)
|
|
1305
|
+
if (bad) {
|
|
1306
|
+
if (state.value.length && cols.value.length) select(0, cols.value[0]!.name)
|
|
1307
|
+
else setSel(null)
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1297
1310
|
}
|
|
1298
1311
|
const undo = () => {
|
|
1299
1312
|
if (!canUndo.value) return
|
|
1300
|
-
|
|
1301
|
-
|
|
1313
|
+
const snapshot = history.undo(takeSnapshot())
|
|
1314
|
+
if (!snapshot) return
|
|
1315
|
+
restoreSnapshot(snapshot)
|
|
1302
1316
|
emit("structure-change", { rows: state.value, columns: cols.value, reason: "undo" })
|
|
1303
1317
|
}
|
|
1304
1318
|
const redo = () => {
|
|
1305
1319
|
if (!canRedo.value) return
|
|
1306
|
-
|
|
1307
|
-
|
|
1320
|
+
const snapshot = history.redo(takeSnapshot())
|
|
1321
|
+
if (!snapshot) return
|
|
1322
|
+
restoreSnapshot(snapshot)
|
|
1308
1323
|
emit("structure-change", { rows: state.value, columns: cols.value, reason: "redo" })
|
|
1309
1324
|
}
|
|
1310
1325
|
|
|
@@ -3143,10 +3158,17 @@ const endResize = () => {
|
|
|
3143
3158
|
window.removeEventListener("pointerup", endResize)
|
|
3144
3159
|
}
|
|
3145
3160
|
|
|
3146
|
-
const onPointerUpGlobal = () => {
|
|
3161
|
+
const onPointerUpGlobal = (e: PointerEvent) => {
|
|
3147
3162
|
isPointerDown.value = false
|
|
3148
3163
|
endResize()
|
|
3149
3164
|
endRowResize()
|
|
3165
|
+
const target = e.target as HTMLElement | null
|
|
3166
|
+
// Ne restaurer le focus de la grille que si le geste se termine **dans la grille**,
|
|
3167
|
+
// et jamais depuis l'éditeur / ses listes. Sinon `td.focus()` déclenche le `blur`
|
|
3168
|
+
// de l'input **avant** le `click` de l'option : `commitEdit()` ferme l'éditeur et
|
|
3169
|
+
// la valeur cliquée (`select` / `multiselect`) était perdue.
|
|
3170
|
+
if (!target?.closest?.(".q-spreadsheet__viewport")) return
|
|
3171
|
+
if (target.closest(".q-spreadsheet__editor")) return
|
|
3150
3172
|
const s = sel.value
|
|
3151
3173
|
if (s) focusCell(s.row, s.column)
|
|
3152
3174
|
}
|
|
@@ -3353,8 +3375,7 @@ const loadSheetIntoEngine = (idx: number) => {
|
|
|
3353
3375
|
colWidths.value = { ...ext.widths }
|
|
3354
3376
|
setSel(null)
|
|
3355
3377
|
editing.value = null
|
|
3356
|
-
|
|
3357
|
-
redoStack.length = 0
|
|
3378
|
+
history.clear()
|
|
3358
3379
|
if (scrollEl.value) scrollEl.value.scrollTop = 0
|
|
3359
3380
|
}
|
|
3360
3381
|
/**
|
|
@@ -3766,7 +3787,10 @@ const findReplaceCurrent = () => {
|
|
|
3766
3787
|
const next = findCase.value
|
|
3767
3788
|
? raw.split(findQuery.value).join(findReplaceText.value)
|
|
3768
3789
|
: raw.replace(new RegExp(escapeRegExp(findQuery.value), "gi"), findReplaceText.value)
|
|
3769
|
-
if (next !== raw)
|
|
3790
|
+
if (next !== raw) {
|
|
3791
|
+
pushHistory()
|
|
3792
|
+
setCellValue(m.r, m.name, raw, next)
|
|
3793
|
+
}
|
|
3770
3794
|
findScan()
|
|
3771
3795
|
findNext(1)
|
|
3772
3796
|
}
|
|
@@ -4306,6 +4330,7 @@ const validateAndSet = async (r: number, name: string, old: any, next: any): Pro
|
|
|
4306
4330
|
return false
|
|
4307
4331
|
}
|
|
4308
4332
|
clearValError(r, name)
|
|
4333
|
+
pushHistory()
|
|
4309
4334
|
setCellValue(r, name, old, next)
|
|
4310
4335
|
return true
|
|
4311
4336
|
}
|
package/index.ts
CHANGED
|
@@ -203,19 +203,38 @@ export { DEFAULT_LAYOUT_VIEW, parseView, qLayoutKey } from "./lib/layout"
|
|
|
203
203
|
export type { LayoutView, LayoutZone, LayoutZonePlacement, QLayoutContext } from "./lib/layout"
|
|
204
204
|
export { vRipple } from "./lib/ripple"
|
|
205
205
|
export type { RippleOptions, RippleValue } from "./lib/ripple"
|
|
206
|
-
export { chartToECharts, channelValue, pickFromEvent, tableModel, textValue } from "./lib/chart"
|
|
206
|
+
export { chartToECharts, channelValue, pickFromEvent, tableCsv, tableModel, textValue, tokenCss } from "./lib/chart"
|
|
207
207
|
export type {
|
|
208
208
|
QChartAxis,
|
|
209
209
|
QChartChannel,
|
|
210
210
|
QChartColumn,
|
|
211
211
|
QChartConfig,
|
|
212
|
+
QChartFormat,
|
|
213
|
+
QChartFormatKind,
|
|
214
|
+
QChartFormatOptions,
|
|
215
|
+
QChartGaugeBand,
|
|
212
216
|
QChartLegend,
|
|
213
217
|
QChartMark,
|
|
214
218
|
QChartMarkType,
|
|
215
219
|
QChartOrientation,
|
|
216
220
|
QChartTable,
|
|
221
|
+
QChartTableTotals,
|
|
222
|
+
QChartTableView,
|
|
223
|
+
QChartThreshold,
|
|
224
|
+
QChartTooltip,
|
|
217
225
|
QChartPick,
|
|
218
226
|
} from "./lib/chart"
|
|
227
|
+
export { DEFAULT_CURRENCY, DEFAULT_LOCALE, formatValue } from "./lib/chartFormat"
|
|
228
|
+
export { boxStats, histogram, linearFit, waterfallSteps } from "./lib/chartStats"
|
|
229
|
+
export { cellBarGeometry, cellScale, cellVisualOf, sparklineGeometry } from "./lib/chartTable"
|
|
230
|
+
export type {
|
|
231
|
+
QChartCellBar,
|
|
232
|
+
QChartCellKind,
|
|
233
|
+
QChartCellScale,
|
|
234
|
+
QChartCellVisual,
|
|
235
|
+
QChartSparkPoint,
|
|
236
|
+
QChartSparkline,
|
|
237
|
+
} from "./lib/chartTable"
|
|
219
238
|
export { vTouchPan } from "./lib/touchPan"
|
|
220
239
|
export type { PanDetails, TouchPanHandler, PanDirection } from "./lib/touchPan"
|
|
221
240
|
export { vTouchHold } from "./lib/touchHold"
|
package/lib/chart.axis.test.ts
CHANGED
|
@@ -28,7 +28,7 @@ function renderSvg(config: Record<string, any>, width: number, height: number):
|
|
|
28
28
|
width,
|
|
29
29
|
height,
|
|
30
30
|
})
|
|
31
|
-
chart.setOption(chartToECharts({ theme: THEME, ...config }))
|
|
31
|
+
chart.setOption(chartToECharts({ marks: [], theme: THEME, ...config }))
|
|
32
32
|
const svg = chart.renderToSVGString()
|
|
33
33
|
chart.dispose()
|
|
34
34
|
return svg
|