@dnax/ui 0.0.41 → 0.0.42

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.
@@ -400,12 +400,18 @@ const newRowKey = (): string => {
400
400
  return `row-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`
401
401
  }
402
402
 
403
- /** Injecte `_key` (mutatif) sur les lignes qui n'en ont pas encore */
403
+ /**
404
+ * Injecte `_key` (mutatif) uniquement sur les lignes qui n'en ont pas.
405
+ * Une clé DÉJÀ PRÉSENTE est toujours conservée, quelle que soit sa valeur
406
+ * (string, nombre, uuid ou non) : l'injection ne s'applique qu'à
407
+ * `undefined` / `null` / chaîne vide. Aucune réécriture, aucun dédoublonnage.
408
+ */
404
409
  const ensureRowKeys = (rows: Record<string, any>[] | undefined) => {
405
410
  if (!Array.isArray(rows)) return
406
411
  for (const row of rows) {
407
412
  if (!row || typeof row !== "object") continue
408
- if (typeof row[ROW_KEY] !== "string" || !row[ROW_KEY]) row[ROW_KEY] = newRowKey()
413
+ const current = row[ROW_KEY]
414
+ if (current === undefined || current === null || current === "") row[ROW_KEY] = newRowKey()
409
415
  }
410
416
  }
411
417
 
@@ -687,22 +693,19 @@ const editingIsFormula = computed(() => {
687
693
  if (!editing.value) return false
688
694
  const col = colOf(editing.value.column)
689
695
  if (!col || col.type === "boolean" || col.type === "select") return false
690
- return draft.value.trim().startsWith("=")
696
+ return String(draft.value ?? "").trim().startsWith("=")
691
697
  })
692
698
  const editingIsSelect = computed(() => {
693
699
  const col = editing.value ? colOf(editing.value.column) : undefined
694
700
  return col?.type === "select"
695
701
  })
696
702
  const draftLines = computed(() =>
697
- Math.min(5, Math.max(1, draft.value.split("\n").length)),
703
+ Math.min(5, Math.max(1, String(draft.value ?? "").split("\n").length)),
698
704
  )
699
705
 
700
706
  const editorInputType = computed(() => {
701
707
  const col = editing.value ? colOf(editing.value.column) : undefined
702
708
  switch (col?.type) {
703
- case "number":
704
- case "integer":
705
- return "number"
706
709
  case "email":
707
710
  return "email"
708
711
  case "url":
@@ -712,15 +715,20 @@ const editorInputType = computed(() => {
712
715
  case "datetime":
713
716
  return "datetime-local"
714
717
  default:
718
+ // PAS de `type="number"` pour number/integer : (1) le navigateur refuse
719
+ // `=` (formule) ou un "-" isolé dans un input number, (2) `v-model` sur
720
+ // input[type=number] **caste la valeur en Number** → le brouillon n'était
721
+ // plus une string et tous les `.trim()` / `.split()` dessus explosaient.
722
+ // Le clavier numérique mobile est assuré par `inputmode` (`editorInputMode`).
715
723
  return "text"
716
724
  }
717
725
  })
718
726
 
719
- /** step natif : "any" (décimales) pour number, "1" pour integer */
720
- const editorStep = computed(() => {
727
+ /** Équivalent mobile de `type="number"` : clavier décimal / numérique sans cast */
728
+ const editorInputMode = computed(() => {
721
729
  const col = editing.value ? colOf(editing.value.column) : undefined
722
- if (col?.type === "number") return "any"
723
- if (col?.type === "integer") return "1"
730
+ if (col?.type === "number") return "decimal"
731
+ if (col?.type === "integer") return "numeric"
724
732
  return undefined
725
733
  })
726
734
 
@@ -757,7 +765,7 @@ const positionEditor = () => {
757
765
  // Une formule élargit l'éditeur (monospace ≈ 7.6px/car), sans dépasser le bord droit
758
766
  const maxW = sc.width - (tr.left - sc.left) - 4
759
767
  const ideal = editingIsFormula.value
760
- ? Math.min(480, Math.max(220, draft.value.length * 7.6 + 30))
768
+ ? Math.min(480, Math.max(220, String(draft.value ?? "").length * 7.6 + 30))
761
769
  : tr.width
762
770
  const width = Math.min(maxW, Math.max(tr.width, ideal))
763
771
  editorStyle.value = {
@@ -1499,7 +1507,7 @@ const selectOptions = computed<QSpreadsheetCellOption[]>(() => {
1499
1507
  if (!editing.value) return []
1500
1508
  const col = colOf(editing.value.column)
1501
1509
  if (col?.type !== "select") return []
1502
- const q = draft.value.trim().toLowerCase()
1510
+ const q = String(draft.value ?? "").trim().toLowerCase()
1503
1511
  return (col.options ?? []).filter(
1504
1512
  (o) => !q || String(o.label ?? o.value ?? "").toLowerCase().includes(q),
1505
1513
  )
@@ -1689,8 +1697,8 @@ const acceptFx = () => {
1689
1697
  const f = fxSuggestions.value[fxActive.value]
1690
1698
  if (!f) return
1691
1699
  const replaceTail = (s: string) => s.replace(/[A-Za-z]+$/, f.name + "(")
1692
- if (editing.value) draft.value = replaceTail(draft.value)
1693
- else fxDraft.value = replaceTail(fxDraft.value)
1700
+ if (editing.value) draft.value = replaceTail(String(draft.value ?? ""))
1701
+ else fxDraft.value = replaceTail(String(fxDraft.value ?? ""))
1694
1702
  fxActive.value = 0
1695
1703
  nextTick(() => {
1696
1704
  const el = editing.value
@@ -4377,7 +4385,7 @@ defineExpose({
4377
4385
  v-model="draft"
4378
4386
  class="q-spreadsheet__editor-input"
4379
4387
  :type="editorInputType"
4380
- :step="editorStep"
4388
+ :inputmode="editorInputMode"
4381
4389
  :placeholder="editingCol.type === 'select' ? 'Type to filter…' : ''"
4382
4390
  @keydown="onEditKeydown"
4383
4391
  @blur="commitEdit"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dnax/ui",
3
- "version": "0.0.41",
3
+ "version": "0.0.42",
4
4
  "module": "index.ts",
5
5
  "description": "UI design System",
6
6
  "type": "module",