@dnax/ui 0.0.73 → 0.0.76
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/QBtnDropdown.vue +8 -1
- package/components/QCard.vue +3 -3
- package/components/QDialog.vue +2 -2
- package/components/QFilePicker.vue +22 -65
- package/components/QGridItem.vue +1 -1
- package/components/QImg.vue +3 -1
- package/components/QInputOtp.vue +2 -0
- package/components/QSpreadsheet.vue +593 -65
- package/components/QSyntax.vue +2 -2
- package/components/QTable.vue +2 -2
- package/index.ts +18 -0
- package/lib/cellSize.test.ts +52 -0
- package/lib/cellSize.ts +43 -0
- package/lib/fileList.test.ts +119 -0
- package/lib/fileList.ts +159 -0
- package/lib/iconSet.test.ts +61 -0
- package/lib/iconSet.ts +91 -0
- package/lib/iconSetScrape.ts +139 -0
- package/lib/icons.ts +16 -0
- package/lib/pagination.test.ts +77 -0
- package/lib/pagination.ts +50 -0
- package/lib/registerIcons.ts +37 -0
- package/lib/useComponentProps.test.ts +55 -1
- package/lib/useComponentProps.ts +15 -0
- package/module.ts +124 -6
- package/package.json +4 -2
- package/runtime.ts +5 -0
- package/scripts/gen-icon-set.ts +110 -0
- package/scripts/generate-exports.ts +46 -69
- package/styles/main.css +191 -1
|
@@ -31,6 +31,7 @@ export interface DropdownItem {
|
|
|
31
31
|
import { computed } from "vue"
|
|
32
32
|
import type { StyleValue } from "vue"
|
|
33
33
|
import QBtnActions, { type DropdownPosition } from "./QBtnActions.vue"
|
|
34
|
+
import { useRadius } from "../lib/useComponentProps"
|
|
34
35
|
import type { RadiusProp } from "../lib/useComponentProps"
|
|
35
36
|
|
|
36
37
|
interface Props {
|
|
@@ -115,6 +116,12 @@ const mappedActions = computed(() =>
|
|
|
115
116
|
)
|
|
116
117
|
|
|
117
118
|
const onSelectAction = (value: any) => emit("select", value)
|
|
119
|
+
|
|
120
|
+
// radius : prop explicite > composantProps.QBtnDropdown > composantProps.default.
|
|
121
|
+
// On transmet la valeur **résolue** (et non la prop brute) pour que
|
|
122
|
+
// `componentProps.QBtnDropdown.radius` ne soit pas ignoré au profit de celui du
|
|
123
|
+
// moteur QBtnActions.
|
|
124
|
+
const effectiveRadius = useRadius("QBtnDropdown", () => props.radius)
|
|
118
125
|
</script>
|
|
119
126
|
|
|
120
127
|
<template>
|
|
@@ -134,7 +141,7 @@ const onSelectAction = (value: any) => emit("select", value)
|
|
|
134
141
|
:color="color"
|
|
135
142
|
:text-color="textColor"
|
|
136
143
|
:size="size"
|
|
137
|
-
:radius="
|
|
144
|
+
:radius="effectiveRadius"
|
|
138
145
|
:flat="flat"
|
|
139
146
|
:outline="outline"
|
|
140
147
|
:unelevated="unelevated"
|
package/components/QCard.vue
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Pas d'ombre par défaut ; elevated l'ajoute, flat la retire explicitement.
|
|
4
4
|
// Slots : default, media (zone image en haut), actions (zone actions en bas)
|
|
5
5
|
import { computed } from "vue"
|
|
6
|
-
import {
|
|
6
|
+
import { radiusStyleNative, useRadius } from "../lib/useComponentProps"
|
|
7
7
|
import type { RadiusProp } from "../lib/useComponentProps"
|
|
8
8
|
|
|
9
9
|
interface Props {
|
|
@@ -35,9 +35,9 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
35
35
|
hover: false,
|
|
36
36
|
})
|
|
37
37
|
|
|
38
|
-
// radius : prop explicite > composantProps.QCard.radius ; échelle → --q-radius
|
|
38
|
+
// radius : prop explicite > composantProps.QCard.radius ; échelle → --q-radius (true = md)
|
|
39
39
|
const effectiveRadius = useRadius("QCard", () => props.radius)
|
|
40
|
-
const roundedStyle = computed(() =>
|
|
40
|
+
const roundedStyle = computed(() => radiusStyleNative(effectiveRadius.value))
|
|
41
41
|
</script>
|
|
42
42
|
|
|
43
43
|
<template>
|
package/components/QDialog.vue
CHANGED
|
@@ -14,7 +14,7 @@ export const qDialogKey: InjectionKey<DialogContext> = Symbol("q-dialog")
|
|
|
14
14
|
import { computed, onBeforeUnmount, onMounted, provide, watch } from "vue"
|
|
15
15
|
import type { StyleValue } from "vue"
|
|
16
16
|
import { cn } from "../lib/utils"
|
|
17
|
-
import {
|
|
17
|
+
import { radiusStyleNative, useRadius } from "../lib/useComponentProps"
|
|
18
18
|
import type { RadiusProp } from "../lib/useComponentProps"
|
|
19
19
|
import { useOverlayBack } from "../lib/overlayBack"
|
|
20
20
|
import { markOverlayClose } from "../lib/closeOverlay"
|
|
@@ -150,7 +150,7 @@ const overlayClasses = computed(() => cn("q-dialog__overlay", `q-dialog__overlay
|
|
|
150
150
|
|
|
151
151
|
// radius : prop explicite > composantProps.QDialog.radius ; échelle → --q-radius
|
|
152
152
|
const effectiveRadius = useRadius("QDialog", () => props.radius)
|
|
153
|
-
const roundedStyle = computed(() =>
|
|
153
|
+
const roundedStyle = computed(() => radiusStyleNative(effectiveRadius.value))
|
|
154
154
|
|
|
155
155
|
const contentClasses = computed(() =>
|
|
156
156
|
cn(
|
|
@@ -6,6 +6,8 @@ import { computed, onBeforeUnmount, reactive, ref, watch } from "vue"
|
|
|
6
6
|
import { Icon } from "@iconify/vue"
|
|
7
7
|
import { icons } from "../lib/icons"
|
|
8
8
|
import { cn } from "../lib/utils"
|
|
9
|
+
import { fileIconKind, formatFileSize, selectFiles } from "../lib/fileList"
|
|
10
|
+
import type { FileIconKind } from "../lib/fileList"
|
|
9
11
|
|
|
10
12
|
interface Props {
|
|
11
13
|
/** Fichier(s) sélectionné(s) — File (simple) ou File[] (multiple) */
|
|
@@ -100,51 +102,20 @@ const fileKey = (file: File): number => {
|
|
|
100
102
|
return id
|
|
101
103
|
}
|
|
102
104
|
|
|
103
|
-
// — Icône par type de fichier (
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (type.startsWith("audio/")) return icons.fileAudio
|
|
113
|
-
if (ARCHIVE_EXT.test(name) || /zip|compressed/.test(type)) return icons.fileArchive
|
|
114
|
-
if (SPREADSHEET_EXT.test(name) || type.includes("spreadsheet") || type.includes("excel")) {
|
|
115
|
-
return icons.fileSpreadsheet
|
|
116
|
-
}
|
|
117
|
-
if (CODE_EXT.test(name)) return icons.fileCode
|
|
118
|
-
if (type.startsWith("image/")) return icons.fileImage
|
|
119
|
-
return icons.fileText
|
|
105
|
+
// — Icône par type de fichier (règles partagées avec QSpreadsheet `attachment`) —
|
|
106
|
+
const ICON_BY_KIND: Record<FileIconKind, string> = {
|
|
107
|
+
image: icons.fileImage,
|
|
108
|
+
video: icons.fileVideo,
|
|
109
|
+
audio: icons.fileAudio,
|
|
110
|
+
archive: icons.fileArchive,
|
|
111
|
+
spreadsheet: icons.fileSpreadsheet,
|
|
112
|
+
code: icons.fileCode,
|
|
113
|
+
file: icons.fileText,
|
|
120
114
|
}
|
|
121
115
|
|
|
122
|
-
const
|
|
123
|
-
if (bytes >= 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} Go`
|
|
124
|
-
if (bytes >= 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))} Mo`
|
|
125
|
-
if (bytes >= 1024) return `${Math.round(bytes / 1024)} Ko`
|
|
126
|
-
return `${bytes} o`
|
|
127
|
-
}
|
|
116
|
+
const iconFor = (file: File): string => ICON_BY_KIND[fileIconKind(file)]
|
|
128
117
|
|
|
129
|
-
|
|
130
|
-
const acceptsFile = (file: File): boolean => {
|
|
131
|
-
const accept = props.accept.trim()
|
|
132
|
-
if (!accept) return true
|
|
133
|
-
const patterns = accept
|
|
134
|
-
.split(",")
|
|
135
|
-
.map((p) => p.trim().toLowerCase())
|
|
136
|
-
.filter(Boolean)
|
|
137
|
-
if (patterns.length === 0) return true
|
|
138
|
-
const name = file.name.toLowerCase()
|
|
139
|
-
return patterns.some((p) => {
|
|
140
|
-
if (p === "image/*") return file.type.startsWith("image/")
|
|
141
|
-
if (p === "video/*") return file.type.startsWith("video/")
|
|
142
|
-
if (p === "audio/*") return file.type.startsWith("audio/")
|
|
143
|
-
if (p.startsWith(".")) return name.endsWith(p)
|
|
144
|
-
if (p.includes("/")) return file.type.toLowerCase() === p
|
|
145
|
-
return false
|
|
146
|
-
})
|
|
147
|
-
}
|
|
118
|
+
const formatSize = formatFileSize
|
|
148
119
|
|
|
149
120
|
const formatMaxSize = () => {
|
|
150
121
|
const bytes = props.maxFileSize
|
|
@@ -176,26 +147,12 @@ const onInputChange = (e: Event) => {
|
|
|
176
147
|
|
|
177
148
|
const addFiles = (incoming: File[]) => {
|
|
178
149
|
const current = files.value
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
continue
|
|
186
|
-
}
|
|
187
|
-
if (!acceptsFile(file)) {
|
|
188
|
-
rejections.push({ file, reason: "type" })
|
|
189
|
-
continue
|
|
190
|
-
}
|
|
191
|
-
valid.push(file)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const quota = props.maxFiles > 0 ? props.maxFiles : Infinity
|
|
195
|
-
const remaining = quota === Infinity ? Infinity : Math.max(0, quota - current.length)
|
|
196
|
-
const accepted = remaining === Infinity ? valid : valid.slice(0, remaining)
|
|
197
|
-
const overflow = remaining === Infinity ? [] : valid.slice(remaining)
|
|
198
|
-
for (const file of overflow) rejections.push({ file, reason: "count" })
|
|
150
|
+
const { accepted, rejected } = selectFiles(incoming, {
|
|
151
|
+
accept: props.accept,
|
|
152
|
+
maxSize: props.maxFileSize,
|
|
153
|
+
maxFiles: props.maxFiles,
|
|
154
|
+
current: current.length,
|
|
155
|
+
})
|
|
199
156
|
|
|
200
157
|
if (accepted.length > 0) {
|
|
201
158
|
const next = props.multiple ? [...current, ...accepted] : accepted[0]!
|
|
@@ -203,14 +160,14 @@ const addFiles = (incoming: File[]) => {
|
|
|
203
160
|
for (const file of accepted) emit("add", file)
|
|
204
161
|
}
|
|
205
162
|
|
|
206
|
-
if (
|
|
207
|
-
const reasons = [...new Set(
|
|
163
|
+
if (rejected.length > 0) {
|
|
164
|
+
const reasons = [...new Set(rejected.map((r) => r.reason))]
|
|
208
165
|
const parts: string[] = []
|
|
209
166
|
if (reasons.includes("size")) parts.push(`Fichier trop lourd (max ${formatMaxSize()})`)
|
|
210
167
|
if (reasons.includes("type")) parts.push("Type de fichier non accepté")
|
|
211
168
|
if (reasons.includes("count")) parts.push(`Nombre maximum : ${props.maxFiles}`)
|
|
212
169
|
internalError.value = parts.join(" · ")
|
|
213
|
-
for (const r of
|
|
170
|
+
for (const r of rejected) emit("rejected", r.file, r.reason)
|
|
214
171
|
}
|
|
215
172
|
}
|
|
216
173
|
|
package/components/QGridItem.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
// QGridItem — cellule de la grille style Vant : <q-grid-item icon="lucide:
|
|
2
|
+
// QGridItem — cellule de la grille style Vant : <q-grid-item icon="lucide:image" text="Photos" badge="3" />
|
|
3
3
|
// À utiliser dans <q-grid :column-num="…">. Affiche une icône (ou un slot) + un
|
|
4
4
|
// texte, avec badge / point de notification, effet cliquable et navigation (href).
|
|
5
5
|
import { computed } from "vue"
|
package/components/QImg.vue
CHANGED
|
@@ -77,8 +77,10 @@ const imageClasses = computed(() =>
|
|
|
77
77
|
)
|
|
78
78
|
|
|
79
79
|
// radius : prop explicite > composantProps.QImg > composantProps.default → --q-radius
|
|
80
|
+
// `true` = pilule (forme native documentée) → classe dédiée, pas un `--q-radius`
|
|
80
81
|
const effectiveRadius = useRadius("QImg", () => props.radius)
|
|
81
82
|
const roundedStyle = computed(() => radiusStyle(effectiveRadius.value))
|
|
83
|
+
const roundedClass = computed(() => (effectiveRadius.value === true ? "q-img--rounded" : undefined))
|
|
82
84
|
|
|
83
85
|
const imageStyle = computed(() => `${props.imgStyle}; object-position: ${props.position}`)
|
|
84
86
|
|
|
@@ -101,7 +103,7 @@ const showLoading = computed(() => props.loading || imgLoading.value)
|
|
|
101
103
|
</script>
|
|
102
104
|
|
|
103
105
|
<template>
|
|
104
|
-
<div class="q-img" :style="[containerStyle, roundedStyle]">
|
|
106
|
+
<div class="q-img" :class="roundedClass" :style="[containerStyle, roundedStyle]">
|
|
105
107
|
<!-- Placeholder basse résolution pendant le chargement -->
|
|
106
108
|
<img
|
|
107
109
|
v-if="placeholderSrc && imgLoading && !imgError"
|
package/components/QInputOtp.vue
CHANGED
|
@@ -190,6 +190,8 @@ const rootClasses = computed(() =>
|
|
|
190
190
|
props.dense && "q-field--dense",
|
|
191
191
|
props.error && "q-field--error",
|
|
192
192
|
props.disable && "q-field--disabled",
|
|
193
|
+
// `radius: true` = pilule (forme native documentée)
|
|
194
|
+
effectiveRadius.value === true && "q-input-otp--rounded",
|
|
193
195
|
),
|
|
194
196
|
)
|
|
195
197
|
|