@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.
@@ -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 undoStack: Snapshot[] = []
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
- undoStack.push(takeSnapshot())
1278
- if (undoStack.length > 100) undoStack.shift()
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
- redoStack.push(takeSnapshot())
1301
- restoreSnapshot(undoStack.pop()!)
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
- undoStack.push(takeSnapshot())
1307
- restoreSnapshot(redoStack.pop()!)
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
- undoStack.length = 0
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) setCellValue(m.r, m.name, raw, next)
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"
@@ -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