@dnax/ui 0.0.28 → 0.0.29
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/QBar.vue +42 -0
- package/components/QBoard.vue +285 -0
- package/components/QConfigProvider.vue +9 -5
- package/components/QInteract.vue +387 -0
- package/components/QSpreadsheet.vue +4662 -0
- package/index.ts +6 -0
- package/lib/config.ts +6 -0
- package/lib/formula.test.ts +206 -0
- package/lib/formula.ts +292 -0
- package/lib/icons.ts +17 -0
- package/lib/intersection.ts +118 -0
- package/lib/spreadsheet.test.ts +92 -0
- package/lib/spreadsheet.ts +175 -0
- package/lib/useComponentProps.ts +7 -0
- package/module.ts +2 -0
- package/package.json +3 -1
- package/scripts/generate-exports.ts +2 -0
- package/styles/main.css +1344 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// v-intersection — directive : appelle un handler quand l'élément entre /
|
|
2
|
+
// sort du viewport (Intersection Observer), équivalent Quasar
|
|
3
|
+
// https://quasar.dev/vue-directives/intersection
|
|
4
|
+
//
|
|
5
|
+
// Usage :
|
|
6
|
+
// <div v-intersection="onEnter">…</div>
|
|
7
|
+
// <div v-intersection.once="onFirstEnter">…</div>
|
|
8
|
+
// <div v-intersection="{ handler, cfg: { rootMargin: '0px', threshold: 0.2 } }">…</div>
|
|
9
|
+
// <div v-intersection="false">…</div> (désactive l'observation)
|
|
10
|
+
//
|
|
11
|
+
// Le handler reçoit un IntersectionObserverEntry. Les éléments partageant les
|
|
12
|
+
// mêmes options (cfg) utilisent le même IntersectionObserver sous le capot.
|
|
13
|
+
|
|
14
|
+
export type IntersectionValue =
|
|
15
|
+
| ((entry: IntersectionObserverEntry) => void)
|
|
16
|
+
| { handler: (entry: IntersectionObserverEntry) => void; cfg?: IntersectionObserverInit }
|
|
17
|
+
| false
|
|
18
|
+
| undefined
|
|
19
|
+
| null
|
|
20
|
+
|
|
21
|
+
type PoolEntry = {
|
|
22
|
+
key: string
|
|
23
|
+
observer: IntersectionObserver
|
|
24
|
+
elements: Set<Element>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type QElement = HTMLElement & {
|
|
28
|
+
__qIntersection?: {
|
|
29
|
+
key: string
|
|
30
|
+
observer: IntersectionObserver
|
|
31
|
+
handler: (e: IntersectionObserverEntry) => void
|
|
32
|
+
once: boolean
|
|
33
|
+
raw: IntersectionValue
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const pool = new Map<string, PoolEntry>()
|
|
38
|
+
|
|
39
|
+
function getPoolEntry(cfg: IntersectionObserverInit): PoolEntry {
|
|
40
|
+
const key = JSON.stringify([
|
|
41
|
+
cfg.rootMargin ?? "0px",
|
|
42
|
+
cfg.threshold ?? 0,
|
|
43
|
+
cfg.root === null ? null : cfg.root instanceof Element ? (cfg.root as Element).id || "" : String(cfg.root),
|
|
44
|
+
])
|
|
45
|
+
let entry = pool.get(key)
|
|
46
|
+
if (!entry) {
|
|
47
|
+
const elements = new Set<Element>()
|
|
48
|
+
const observer = new IntersectionObserver((entries) => {
|
|
49
|
+
for (const e of entries) {
|
|
50
|
+
const rec = (e.target as QElement).__qIntersection
|
|
51
|
+
if (!rec) continue
|
|
52
|
+
if (rec.once && e.isIntersecting) {
|
|
53
|
+
rec.handler(e)
|
|
54
|
+
unobserve(e.target as QElement)
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
rec.handler(e)
|
|
58
|
+
}
|
|
59
|
+
}, cfg)
|
|
60
|
+
entry = { key, observer, elements }
|
|
61
|
+
pool.set(key, entry)
|
|
62
|
+
}
|
|
63
|
+
return entry
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function unobserve(el: QElement) {
|
|
67
|
+
const rec = el.__qIntersection
|
|
68
|
+
if (!rec) return
|
|
69
|
+
const entry = pool.get(rec.key)
|
|
70
|
+
el.__qIntersection = undefined
|
|
71
|
+
rec.observer.unobserve(el)
|
|
72
|
+
if (entry) {
|
|
73
|
+
entry.elements.delete(el)
|
|
74
|
+
if (entry.elements.size === 0) {
|
|
75
|
+
entry.observer.disconnect()
|
|
76
|
+
pool.delete(rec.key)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function apply(el: HTMLElement, value: IntersectionValue, once = false) {
|
|
82
|
+
const target = el as QElement
|
|
83
|
+
if (target.__qIntersection) unobserve(target)
|
|
84
|
+
if (!value) return
|
|
85
|
+
|
|
86
|
+
let handler: (entry: IntersectionObserverEntry) => void
|
|
87
|
+
let cfg: IntersectionObserverInit = { root: null, rootMargin: "0px", threshold: 0 }
|
|
88
|
+
|
|
89
|
+
if (typeof value === "function") {
|
|
90
|
+
handler = value
|
|
91
|
+
}
|
|
92
|
+
else if (typeof value === "object") {
|
|
93
|
+
handler = value.handler
|
|
94
|
+
if (value.cfg) cfg = { ...value.cfg }
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const entry = getPoolEntry(cfg)
|
|
101
|
+
target.__qIntersection = { key: entry.key, observer: entry.observer, handler, once, raw: value }
|
|
102
|
+
entry.elements.add(el)
|
|
103
|
+
entry.observer.observe(el)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const vIntersection = {
|
|
107
|
+
mounted(el: HTMLElement, binding: { value?: IntersectionValue; modifiers?: Record<string, boolean> }) {
|
|
108
|
+
apply(el, binding.value, !!binding.modifiers?.once)
|
|
109
|
+
},
|
|
110
|
+
updated(el: HTMLElement, binding: { value?: IntersectionValue; modifiers?: Record<string, boolean> }) {
|
|
111
|
+
const rec = (el as QElement).__qIntersection
|
|
112
|
+
if (rec && rec.raw === binding.value) return
|
|
113
|
+
apply(el, binding.value, !!binding.modifiers?.once)
|
|
114
|
+
},
|
|
115
|
+
unmounted(el: HTMLElement) {
|
|
116
|
+
unobserve(el as QElement)
|
|
117
|
+
},
|
|
118
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Tests unitaires des helpers purs du tableur (bun test).
|
|
2
|
+
import { describe, expect, it } from "bun:test"
|
|
3
|
+
import {
|
|
4
|
+
colLetter,
|
|
5
|
+
colFromLetters,
|
|
6
|
+
isBlankValue,
|
|
7
|
+
isoAddDays,
|
|
8
|
+
shiftFormulaRefs,
|
|
9
|
+
csvEscape,
|
|
10
|
+
csvSplitLine,
|
|
11
|
+
parseCsv,
|
|
12
|
+
deriveCols,
|
|
13
|
+
} from "./spreadsheet"
|
|
14
|
+
|
|
15
|
+
describe("lettres de colonnes", () => {
|
|
16
|
+
it("colLetter : 0→A, 25→Z, 26→AA, 27→AB, 701→ZZ, 702→AAA", () => {
|
|
17
|
+
expect(colLetter(0)).toBe("A")
|
|
18
|
+
expect(colLetter(25)).toBe("Z")
|
|
19
|
+
expect(colLetter(26)).toBe("AA")
|
|
20
|
+
expect(colLetter(27)).toBe("AB")
|
|
21
|
+
expect(colLetter(701)).toBe("ZZ")
|
|
22
|
+
expect(colLetter(702)).toBe("AAA")
|
|
23
|
+
})
|
|
24
|
+
it("colFromLetters est l'inverse", () => {
|
|
25
|
+
expect(colFromLetters("A")).toBe(0)
|
|
26
|
+
expect(colFromLetters("AA")).toBe(26)
|
|
27
|
+
expect(colFromLetters("zz")).toBe(701)
|
|
28
|
+
for (let i = 0; i < 200; i++) expect(colFromLetters(colLetter(i))).toBe(i)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe("shiftFormulaRefs (autofill)", () => {
|
|
33
|
+
it("décale les références relatives de (dr,dc)", () => {
|
|
34
|
+
expect(shiftFormulaRefs("=B1*C1", 1, 0)).toBe("=B2*C2")
|
|
35
|
+
expect(shiftFormulaRefs("=A1", 0, 2)).toBe("=C1")
|
|
36
|
+
})
|
|
37
|
+
it("préserve les $ absolus", () => {
|
|
38
|
+
expect(shiftFormulaRefs("=$B$1+A1", 2, 0)).toBe("=$B$1+A3")
|
|
39
|
+
expect(shiftFormulaRefs("=$B1+B$1", 1, 1)).toBe("=$B2+C$1")
|
|
40
|
+
})
|
|
41
|
+
it("décale les plages entières", () => {
|
|
42
|
+
expect(shiftFormulaRefs("=SUM(D1:D4)", 1, 0)).toBe("=SUM(D2:D5)")
|
|
43
|
+
})
|
|
44
|
+
it("laisse les valeurs sans lettres intactes", () => {
|
|
45
|
+
expect(shiftFormulaRefs("=1+2", 1, 1)).toBe("=1+2")
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
describe("dates ISO", () => {
|
|
50
|
+
it("isoAddDays", () => {
|
|
51
|
+
expect(isoAddDays("2026-09-07", 1)).toBe("2026-09-08")
|
|
52
|
+
expect(isoAddDays("2026-09-07", -7)).toBe("2026-08-31")
|
|
53
|
+
expect(isoAddDays("2026-12-31", 1)).toBe("2027-01-01")
|
|
54
|
+
})
|
|
55
|
+
it("isBlankValue", () => {
|
|
56
|
+
expect(isBlankValue(null)).toBe(true)
|
|
57
|
+
expect(isBlankValue(undefined)).toBe(true)
|
|
58
|
+
expect(isBlankValue("")).toBe(true)
|
|
59
|
+
expect(isBlankValue(0)).toBe(false)
|
|
60
|
+
expect(isBlankValue("0")).toBe(false)
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
describe("CSV", () => {
|
|
65
|
+
it("csvEscape quote si nécessaire", () => {
|
|
66
|
+
expect(csvEscape("simple", ",")).toBe("simple")
|
|
67
|
+
expect(csvEscape("a,b", ",")).toBe('"a,b"')
|
|
68
|
+
expect(csvEscape('say "hi"', ",")).toBe('"say ""hi"""')
|
|
69
|
+
expect(csvEscape("ligne\nsuivante", ";")).toBe('"ligne\nsuivante"')
|
|
70
|
+
expect(csvEscape(null, ",")).toBe("")
|
|
71
|
+
})
|
|
72
|
+
it("csvSplitLine gère les guillemets doublés et les délimiteurs", () => {
|
|
73
|
+
expect(csvSplitLine('a,"b,c",d', ",")).toEqual(["a", "b,c", "d"])
|
|
74
|
+
expect(csvSplitLine('"x""y",z', ",")).toEqual(['x"y', "z"])
|
|
75
|
+
expect(csvSplitLine("a;b", ";")).toEqual(["a", "b"])
|
|
76
|
+
})
|
|
77
|
+
it("parseCsv : multiligne, quotes, CRLF", () => {
|
|
78
|
+
const text = 'h1,h2\r\n"a,1","b""2"\r\nc,d\n'
|
|
79
|
+
expect(parseCsv(text)).toEqual([
|
|
80
|
+
["h1", "h2"],
|
|
81
|
+
["a,1", 'b"2'],
|
|
82
|
+
["c", "d"],
|
|
83
|
+
])
|
|
84
|
+
})
|
|
85
|
+
it("deriveCols déduit les colonnes des clés", () => {
|
|
86
|
+
expect(deriveCols([{ a: 1, b: "x" }, { b: 2, c: true }])).toEqual([
|
|
87
|
+
{ name: "a", type: "text" },
|
|
88
|
+
{ name: "b", type: "text" },
|
|
89
|
+
{ name: "c", type: "text" },
|
|
90
|
+
])
|
|
91
|
+
})
|
|
92
|
+
})
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// Helpers purs du tableur QSpreadsheet — extraits du composant pour être
|
|
2
|
+
// testables unitairement (bun test). Aucune dépendance DOM / Vue.
|
|
3
|
+
|
|
4
|
+
/** Index de colonne (0-based) → lettres Excel : 0 → "A", 25 → "Z", 26 → "AA" */
|
|
5
|
+
export const colLetter = (i: number): string => {
|
|
6
|
+
let n = i
|
|
7
|
+
let s = ""
|
|
8
|
+
while (n >= 0) {
|
|
9
|
+
s = String.fromCharCode(65 + (n % 26)) + s
|
|
10
|
+
n = Math.floor(n / 26) - 1
|
|
11
|
+
}
|
|
12
|
+
return s
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Lettres Excel → index de colonne 0-based : "A" → 0, "AA" → 26 */
|
|
16
|
+
export const colFromLetters = (s: string): number => {
|
|
17
|
+
let n = 0
|
|
18
|
+
for (const ch of s.toUpperCase()) n = n * 26 + (ch.charCodeAt(0) - 64)
|
|
19
|
+
return n - 1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Cellule « vide » : null, undefined ou chaîne vide */
|
|
23
|
+
export const isBlankValue = (v: any): boolean =>
|
|
24
|
+
v === null || v === undefined || v === ""
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Décale les références A1 non absolues d'une formule de (dr, dc) —
|
|
28
|
+
* plages incluses, `$` préservés (copie / autofill).
|
|
29
|
+
*/
|
|
30
|
+
export const shiftFormulaRefs = (src: string, dr: number, dc: number): string =>
|
|
31
|
+
src.replace(
|
|
32
|
+
/(\$?)([A-Za-z]{1,3})(\$?)(\d+)/g,
|
|
33
|
+
(_m: string, ca: string, L: string, ra: string, D: string) => {
|
|
34
|
+
const col = colFromLetters(L) + (ca === "$" ? 0 : dc)
|
|
35
|
+
const row = Number(D) - 1 + (ra === "$" ? 0 : dr)
|
|
36
|
+
if (col < 0 || row < 0) return _m
|
|
37
|
+
return ca + colLetter(col) + ra + (row + 1)
|
|
38
|
+
},
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
/** Date ISO AAAA-MM-JJ */
|
|
42
|
+
export const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/
|
|
43
|
+
|
|
44
|
+
/** Ajoute des jours à une date ISO (UTC, évite le décalage de fuseau) */
|
|
45
|
+
export const isoAddDays = (iso: string, days: number): string => {
|
|
46
|
+
const d = new Date(iso + "T00:00:00Z")
|
|
47
|
+
d.setUTCDate(d.getUTCDate() + days)
|
|
48
|
+
return d.toISOString().slice(0, 10)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Échappe une valeur pour un CSV (quote si délimiteur / guillemet / newline) */
|
|
52
|
+
export const csvEscape = (s: unknown, delim: string): string => {
|
|
53
|
+
const str = s === null || s === undefined ? "" : String(s)
|
|
54
|
+
return str.includes(delim) || str.includes('"') || /[\n\r]/.test(str)
|
|
55
|
+
? '"' + str.replace(/"/g, '""') + '"'
|
|
56
|
+
: str
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Décode une ligne CSV (guillemets doublés, délimiteur multi-caractère géré
|
|
61
|
+
* comme un caractère unique ; retourne les cellules décodées).
|
|
62
|
+
*/
|
|
63
|
+
export const csvSplitLine = (line: string, delim = ","): string[] => {
|
|
64
|
+
const out: string[] = []
|
|
65
|
+
let cur = ""
|
|
66
|
+
let inQ = false
|
|
67
|
+
let i = 0
|
|
68
|
+
const isDelim = (at: number) => line.startsWith(delim, at)
|
|
69
|
+
while (i < line.length) {
|
|
70
|
+
const ch = line[i]!
|
|
71
|
+
if (inQ) {
|
|
72
|
+
if (ch === '"') {
|
|
73
|
+
if (line[i + 1] === '"') {
|
|
74
|
+
cur += '"'
|
|
75
|
+
i += 2
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
inQ = false
|
|
79
|
+
i++
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
cur += ch
|
|
83
|
+
i++
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
if (ch === '"') {
|
|
87
|
+
inQ = true
|
|
88
|
+
i++
|
|
89
|
+
continue
|
|
90
|
+
}
|
|
91
|
+
if (isDelim(i)) {
|
|
92
|
+
out.push(cur)
|
|
93
|
+
cur = ""
|
|
94
|
+
i += delim.length
|
|
95
|
+
continue
|
|
96
|
+
}
|
|
97
|
+
cur += ch
|
|
98
|
+
i++
|
|
99
|
+
}
|
|
100
|
+
out.push(cur)
|
|
101
|
+
return out
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Parse un texte CSV complet (CRLF ou LF, guillemets) en lignes de cellules.
|
|
106
|
+
*/
|
|
107
|
+
export const parseCsv = (text: string, delim = ","): string[][] => {
|
|
108
|
+
const lines: string[][] = []
|
|
109
|
+
const current: string[] = []
|
|
110
|
+
let cell = ""
|
|
111
|
+
let inQ = false
|
|
112
|
+
let sawDelim = false
|
|
113
|
+
let i = 0
|
|
114
|
+
const isDelim = (at: number) => text.startsWith(delim, at)
|
|
115
|
+
const pushCell = () => {
|
|
116
|
+
current.push(cell)
|
|
117
|
+
cell = ""
|
|
118
|
+
}
|
|
119
|
+
while (i < text.length) {
|
|
120
|
+
const ch = text[i]!
|
|
121
|
+
if (inQ) {
|
|
122
|
+
if (ch === '"') {
|
|
123
|
+
if (text[i + 1] === '"') {
|
|
124
|
+
cell += '"'
|
|
125
|
+
i += 2
|
|
126
|
+
continue
|
|
127
|
+
}
|
|
128
|
+
inQ = false
|
|
129
|
+
i++
|
|
130
|
+
continue
|
|
131
|
+
}
|
|
132
|
+
cell += ch
|
|
133
|
+
i++
|
|
134
|
+
continue
|
|
135
|
+
}
|
|
136
|
+
if (ch === '"') {
|
|
137
|
+
inQ = true
|
|
138
|
+
i++
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
if (isDelim(i)) {
|
|
142
|
+
pushCell()
|
|
143
|
+
sawDelim = true
|
|
144
|
+
i += delim.length
|
|
145
|
+
continue
|
|
146
|
+
}
|
|
147
|
+
if (ch === "\n") {
|
|
148
|
+
pushCell()
|
|
149
|
+
lines.push(current.splice(0))
|
|
150
|
+
sawDelim = false
|
|
151
|
+
i++
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
154
|
+
if (ch === "\r") {
|
|
155
|
+
// les retours \r\n sont déjà gérés par le \n
|
|
156
|
+
i++
|
|
157
|
+
continue
|
|
158
|
+
}
|
|
159
|
+
cell += ch
|
|
160
|
+
i++
|
|
161
|
+
}
|
|
162
|
+
pushCell()
|
|
163
|
+
const onlyTrailingNewline = current.length === 1 && current[0] === "" && !sawDelim
|
|
164
|
+
if (lines.length === 0 || !onlyTrailingNewline) lines.push(current)
|
|
165
|
+
return lines
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Colonnes déduites des clés d'un jeu de lignes (type texte) */
|
|
169
|
+
export const deriveCols = (
|
|
170
|
+
rows: Record<string, any>[],
|
|
171
|
+
): { name: string; type: "text" }[] => {
|
|
172
|
+
const keys = new Set<string>()
|
|
173
|
+
for (const r of rows) Object.keys(r).forEach((k) => keys.add(k))
|
|
174
|
+
return [...keys].map((k) => ({ name: k, type: "text" as const }))
|
|
175
|
+
}
|
package/lib/useComponentProps.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { computed, inject, toValue } from "vue"
|
|
2
2
|
import type { ComputedRef, MaybeRefOrGetter } from "vue"
|
|
3
3
|
import { qConfigKey } from "./config"
|
|
4
|
+
import type { QAppLang } from "./config"
|
|
4
5
|
|
|
5
6
|
/** Échelle de rayon : none (carré) → lg (très arrondi) */
|
|
6
7
|
export type RadiusScale = "none" | "xs" | "sm" | "md" | "lg"
|
|
@@ -19,6 +20,12 @@ export const RADIUS_VALUES: Record<RadiusScale, string> = {
|
|
|
19
20
|
export const isRadiusScale = (v: unknown): v is RadiusScale =>
|
|
20
21
|
v === "none" || v === "xs" || v === "sm" || v === "md" || v === "lg"
|
|
21
22
|
|
|
23
|
+
/** Langue d'application fournie par QConfigProvider ("en" par défaut). */
|
|
24
|
+
export function useConfigLang(): ComputedRef<QAppLang> {
|
|
25
|
+
const config = inject(qConfigKey, null)
|
|
26
|
+
return computed(() => config?.lang.value ?? "en")
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
/**
|
|
23
30
|
* Props par défaut d'un composant depuis `theme.componentProps` :
|
|
24
31
|
* `default` (appliqué à tous) puis `<Nom>` (spécifique, prioritaire).
|
package/module.ts
CHANGED
|
@@ -97,6 +97,7 @@ import { vTouchPan } from "@dnax/ui/runtime"
|
|
|
97
97
|
import { vTouchHold } from "@dnax/ui/runtime"
|
|
98
98
|
import { vTouchSwipe } from "@dnax/ui/runtime"
|
|
99
99
|
import { vTouchRepeat } from "@dnax/ui/runtime"
|
|
100
|
+
import { vIntersection } from "@dnax/ui/runtime"
|
|
100
101
|
|
|
101
102
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
102
103
|
nuxtApp.vueApp.directive("close", vClose)
|
|
@@ -104,6 +105,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
104
105
|
nuxtApp.vueApp.directive("touch-hold", vTouchHold)
|
|
105
106
|
nuxtApp.vueApp.directive("touch-swipe", vTouchSwipe)
|
|
106
107
|
nuxtApp.vueApp.directive("touch-repeat", vTouchRepeat)
|
|
108
|
+
nuxtApp.vueApp.directive("intersection", vIntersection)
|
|
107
109
|
})
|
|
108
110
|
`,
|
|
109
111
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnax/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.29",
|
|
4
4
|
"module": "index.ts",
|
|
5
5
|
"description": "UI design System",
|
|
6
6
|
"type": "module",
|
|
@@ -50,11 +50,13 @@
|
|
|
50
50
|
"@tiptap/vue-3": "^3.31.3",
|
|
51
51
|
"@videojs/html": "^10.0.0-beta.32",
|
|
52
52
|
"@vueuse/core": "^14.4.0",
|
|
53
|
+
"arktype": "^2.2.3",
|
|
53
54
|
"class-variance-authority": "^0.7.1",
|
|
54
55
|
"clsx": "^2.1.1",
|
|
55
56
|
"embla-carousel": "^8.5.0",
|
|
56
57
|
"embla-carousel-vue": "^8.5.0",
|
|
57
58
|
"fuse.js": "^7.1.0",
|
|
59
|
+
"moment": "^2.30.1",
|
|
58
60
|
"shiki": "^3.0.0",
|
|
59
61
|
"swiper": "^14.2.0",
|
|
60
62
|
"tailwind-merge": "^3.6.0",
|
|
@@ -62,6 +62,8 @@ export { vTouchSwipe } from "./lib/touchSwipe"
|
|
|
62
62
|
export type { TouchSwipeDetails, TouchSwipeHandler, SwipeDirection } from "./lib/touchSwipe"
|
|
63
63
|
export { vTouchRepeat } from "./lib/touchRepeat"
|
|
64
64
|
export type { TouchRepeatDetails, TouchRepeatHandler } from "./lib/touchRepeat"
|
|
65
|
+
export { vIntersection } from "./lib/intersection"
|
|
66
|
+
export type { IntersectionValue } from "./lib/intersection"
|
|
65
67
|
`
|
|
66
68
|
|
|
67
69
|
await Bun.write(indexFile, `${exports}\n${manualExports}`)
|