@dnax/ui 0.0.1

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.
Files changed (150) hide show
  1. package/README.md +15 -0
  2. package/components/QAccordion.vue +68 -0
  3. package/components/QAccordionContent.vue +62 -0
  4. package/components/QAccordionItem.vue +24 -0
  5. package/components/QAccordionTrigger.vue +51 -0
  6. package/components/QActionSheet.vue +159 -0
  7. package/components/QApp.vue +8 -0
  8. package/components/QAutocomplete.vue +316 -0
  9. package/components/QAvatar.vue +92 -0
  10. package/components/QBackHeader.vue +69 -0
  11. package/components/QBackTop.vue +125 -0
  12. package/components/QBadge.vue +55 -0
  13. package/components/QBottomSheet.vue +177 -0
  14. package/components/QBottomSheetFooter.vue +9 -0
  15. package/components/QBottomSheetHeader.vue +35 -0
  16. package/components/QBottomSheetProvider.vue +62 -0
  17. package/components/QBottomSheetTrigger.vue +18 -0
  18. package/components/QBtn.vue +144 -0
  19. package/components/QBtnGroup.vue +31 -0
  20. package/components/QBubble.vue +36 -0
  21. package/components/QBubbleContent.vue +28 -0
  22. package/components/QBubbleGroup.vue +25 -0
  23. package/components/QBubbleReactions.vue +40 -0
  24. package/components/QCard.vue +63 -0
  25. package/components/QCardActions.vue +27 -0
  26. package/components/QCardContent.vue +29 -0
  27. package/components/QCarousel.vue +115 -0
  28. package/components/QCarouselContent.vue +23 -0
  29. package/components/QCarouselItem.vue +20 -0
  30. package/components/QCarouselNav.vue +51 -0
  31. package/components/QCheckbox.vue +146 -0
  32. package/components/QChip.vue +91 -0
  33. package/components/QCircularProgress.vue +122 -0
  34. package/components/QCol.vue +52 -0
  35. package/components/QCollapse.vue +141 -0
  36. package/components/QConfigProvider.vue +164 -0
  37. package/components/QContainer.vue +201 -0
  38. package/components/QCountDown.vue +164 -0
  39. package/components/QCountryPicker.vue +593 -0
  40. package/components/QDataGrid.vue +491 -0
  41. package/components/QDatePicker.vue +250 -0
  42. package/components/QDialog.vue +163 -0
  43. package/components/QDialogFooter.vue +9 -0
  44. package/components/QDialogHeader.vue +41 -0
  45. package/components/QDialogProvider.vue +65 -0
  46. package/components/QDialogTrigger.vue +18 -0
  47. package/components/QFab.vue +80 -0
  48. package/components/QFabAction.vue +48 -0
  49. package/components/QFilePicker.vue +294 -0
  50. package/components/QFooter.vue +72 -0
  51. package/components/QGallery.vue +280 -0
  52. package/components/QGrid.vue +54 -0
  53. package/components/QHeader.vue +38 -0
  54. package/components/QIcon.vue +53 -0
  55. package/components/QImagePicker.vue +248 -0
  56. package/components/QImagePreview.vue +225 -0
  57. package/components/QImagePreviewProvider.vue +35 -0
  58. package/components/QImg.vue +142 -0
  59. package/components/QInfiniteScroll.vue +109 -0
  60. package/components/QInnerLoading.vue +67 -0
  61. package/components/QInput.vue +289 -0
  62. package/components/QInputOtp.vue +238 -0
  63. package/components/QInputPassword.vue +67 -0
  64. package/components/QInputTag.vue +281 -0
  65. package/components/QIntersection.vue +119 -0
  66. package/components/QItem.vue +60 -0
  67. package/components/QItemSection.vue +47 -0
  68. package/components/QLinearProgress.vue +94 -0
  69. package/components/QList.vue +39 -0
  70. package/components/QLoading.vue +77 -0
  71. package/components/QLoadingProvider.vue +41 -0
  72. package/components/QMarquee.vue +56 -0
  73. package/components/QMessageScroller.vue +10 -0
  74. package/components/QMessageScrollerButton.vue +48 -0
  75. package/components/QMessageScrollerContent.vue +31 -0
  76. package/components/QMessageScrollerItem.vue +49 -0
  77. package/components/QMessageScrollerProvider.vue +198 -0
  78. package/components/QMessageScrollerViewport.vue +109 -0
  79. package/components/QNavMenu.vue +75 -0
  80. package/components/QNavMenuContent.vue +10 -0
  81. package/components/QNavMenuItem.vue +60 -0
  82. package/components/QNavMenuTrigger.vue +96 -0
  83. package/components/QNotifyProvider.vue +33 -0
  84. package/components/QNotifyToast.vue +60 -0
  85. package/components/QPage.vue +56 -0
  86. package/components/QPagination.vue +195 -0
  87. package/components/QParallax.vue +124 -0
  88. package/components/QPullToRefresh.vue +138 -0
  89. package/components/QRadio.vue +99 -0
  90. package/components/QRating.vue +105 -0
  91. package/components/QReorder.vue +191 -0
  92. package/components/QRollingText.vue +225 -0
  93. package/components/QRow.vue +23 -0
  94. package/components/QSafeArea.vue +39 -0
  95. package/components/QScrollArea.vue +118 -0
  96. package/components/QSelect.vue +698 -0
  97. package/components/QSeparator.vue +39 -0
  98. package/components/QSidebar.vue +153 -0
  99. package/components/QSidebarContent.vue +14 -0
  100. package/components/QSidebarFooter.vue +14 -0
  101. package/components/QSidebarHeader.vue +14 -0
  102. package/components/QSidebarMenu.vue +9 -0
  103. package/components/QSidebarMenuButton.vue +59 -0
  104. package/components/QSidebarMenuItem.vue +9 -0
  105. package/components/QSidebarTrigger.vue +32 -0
  106. package/components/QSkeleton.vue +95 -0
  107. package/components/QSlider.vue +205 -0
  108. package/components/QSpace.vue +10 -0
  109. package/components/QSpinner.vue +172 -0
  110. package/components/QSplitter.vue +145 -0
  111. package/components/QSticky.vue +181 -0
  112. package/components/QSwipeCell.vue +217 -0
  113. package/components/QSwiper.vue +102 -0
  114. package/components/QSwiperSlide.vue +19 -0
  115. package/components/QSyntax.vue +171 -0
  116. package/components/QTab.vue +175 -0
  117. package/components/QTabPanel.vue +50 -0
  118. package/components/QTabPanels.vue +106 -0
  119. package/components/QTable.vue +575 -0
  120. package/components/QTabs.vue +188 -0
  121. package/components/QText.vue +316 -0
  122. package/components/QTextCaption.vue +122 -0
  123. package/components/QToolbar.vue +28 -0
  124. package/components/QTooltip.vue +313 -0
  125. package/components/QUploader.vue +473 -0
  126. package/components/QVideo.vue +289 -0
  127. package/components/QVirtualScroll.vue +190 -0
  128. package/components/internal/QDateCalendar.vue +153 -0
  129. package/index.ts +151 -0
  130. package/lib/breakpoints.ts +44 -0
  131. package/lib/colors.ts +24 -0
  132. package/lib/config.ts +34 -0
  133. package/lib/countries.ts +261 -0
  134. package/lib/formula.ts +630 -0
  135. package/lib/icons.ts +38 -0
  136. package/lib/loading.ts +75 -0
  137. package/lib/overlayBack.ts +124 -0
  138. package/lib/platform.ts +146 -0
  139. package/lib/primitive.ts +25 -0
  140. package/lib/q.ts +287 -0
  141. package/lib/screen.ts +105 -0
  142. package/lib/search.ts +35 -0
  143. package/lib/themeVars.ts +22 -0
  144. package/lib/useComponentProps.ts +54 -0
  145. package/lib/utils.ts +7 -0
  146. package/module.ts +89 -0
  147. package/package.json +41 -0
  148. package/scripts/generate-exports.ts +56 -0
  149. package/styles/main.css +7627 -0
  150. package/tsconfig.json +33 -0
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # ui
2
+
3
+ To install dependencies:
4
+
5
+ ```bash
6
+ bun install
7
+ ```
8
+
9
+ To run:
10
+
11
+ ```bash
12
+ bun run index.ts
13
+ ```
14
+
15
+ This project was created using `bun init` in bun v1.4.1. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
@@ -0,0 +1,68 @@
1
+ <script lang="ts">
2
+ // QAccordion — accordéon type Accordion shadcn-vue (reka-ui), style Quasar.
3
+ // <q-accordion v-model type="single|multiple" collapsible> + QAccordionItem/Trigger/Content
4
+ import type { InjectionKey } from "vue"
5
+
6
+ export interface AccordionContext {
7
+ isOpen: (value: string) => boolean
8
+ toggle: (value: string) => void
9
+ }
10
+
11
+ export const qAccordionKey: InjectionKey<AccordionContext> = Symbol("q-accordion")
12
+
13
+ export interface AccordionItemContext {
14
+ value: string
15
+ uid: string
16
+ }
17
+
18
+ export const qAccordionItemKey: InjectionKey<AccordionItemContext> = Symbol("q-accordion-item")
19
+ </script>
20
+
21
+ <script setup lang="ts">
22
+ import { provide } from "vue"
23
+
24
+ interface Props {
25
+ /** Valeur(s) ouverte(s) : string (single) ou string[] (multiple) */
26
+ modelValue?: string | string[]
27
+ /** single (un seul ouvert) | multiple */
28
+ type?: "single" | "multiple"
29
+ /** En single : permet de refermer l'item ouvert */
30
+ collapsible?: boolean
31
+ }
32
+
33
+ const props = withDefaults(defineProps<Props>(), {
34
+ type: "single",
35
+ collapsible: false,
36
+ })
37
+
38
+ const emit = defineEmits<{ "update:modelValue": [value: string | string[] | undefined] }>()
39
+
40
+ const isOpen = (value: string): boolean => {
41
+ if (props.type === "multiple") return (props.modelValue as string[] | undefined)?.includes(value) ?? false
42
+ return props.modelValue === value
43
+ }
44
+
45
+ const toggle = (value: string) => {
46
+ if (props.type === "multiple") {
47
+ const list = (props.modelValue as string[] | undefined) ?? []
48
+ emit(
49
+ "update:modelValue",
50
+ list.includes(value) ? list.filter((v) => v !== value) : [...list, value],
51
+ )
52
+ }
53
+ else if (props.modelValue === value) {
54
+ if (props.collapsible) emit("update:modelValue", undefined)
55
+ }
56
+ else {
57
+ emit("update:modelValue", value)
58
+ }
59
+ }
60
+
61
+ provide<AccordionContext>(qAccordionKey, { isOpen, toggle })
62
+ </script>
63
+
64
+ <template>
65
+ <div class="q-accordion">
66
+ <slot />
67
+ </div>
68
+ </template>
@@ -0,0 +1,62 @@
1
+ <script setup lang="ts">
2
+ // QAccordionContent — contenu repliable animé (pattern shadcn/reka-ui).
3
+ // Animation de hauteur mesurée (scrollHeight) : height 0 ↔ hauteur du contenu,
4
+ // overflow hidden → contenu invisible quand réduit (aucun débordement).
5
+ import { computed, inject, nextTick, onMounted, ref, watch } from "vue"
6
+ import { qAccordionItemKey, qAccordionKey } from "./QAccordion.vue"
7
+
8
+ const accordion = inject(qAccordionKey, null)
9
+ const item = inject(qAccordionItemKey, null)
10
+
11
+ const isOpen = computed(() => accordion?.isOpen(item?.value ?? "") ?? false)
12
+
13
+ const rootEl = ref<HTMLElement | null>(null)
14
+ const innerEl = ref<HTMLElement | null>(null)
15
+ const contentHeight = ref(0)
16
+ const measured = ref(false)
17
+
18
+ // Hauteur mesurée du contenu (padding compris)
19
+ const measure = () => {
20
+ const inner = innerEl.value
21
+ if (inner) {
22
+ contentHeight.value = inner.scrollHeight
23
+ measured.value = true
24
+ }
25
+ }
26
+
27
+ const rootStyle = computed<Record<string, string> | undefined>(() => {
28
+ if (!isOpen.value) return { height: "0px" }
29
+ return measured.value ? { height: `${contentHeight.value}px` } : undefined
30
+ })
31
+
32
+ // À l'ouverture : mesurer puis animer 0 → hauteur
33
+ watch(isOpen, async (open) => {
34
+ if (open) {
35
+ await nextTick()
36
+ measure()
37
+ }
38
+ })
39
+
40
+ // À la fin de l'animation d'ouverture : height auto (le contenu peut grandir)
41
+ const onTransitionEnd = () => {
42
+ if (isOpen.value && rootEl.value) rootEl.value.style.height = "auto"
43
+ }
44
+
45
+ onMounted(measure)
46
+ </script>
47
+
48
+ <template>
49
+ <div
50
+ ref="rootEl"
51
+ :id="item?.uid"
52
+ class="q-accordion__content"
53
+ :class="{ 'q-accordion__content--open': isOpen }"
54
+ :style="rootStyle"
55
+ role="region"
56
+ @transitionend="onTransitionEnd"
57
+ >
58
+ <div ref="innerEl" class="q-accordion__content-inner">
59
+ <slot />
60
+ </div>
61
+ </div>
62
+ </template>
@@ -0,0 +1,24 @@
1
+ <script setup lang="ts">
2
+ // QAccordionItem — item de l'accordéon (équivalent AccordionItem). Fournit value + uid aux enfants.
3
+ import { provide } from "vue"
4
+ import { qAccordionItemKey, type AccordionItemContext } from "./QAccordion.vue"
5
+
6
+ let itemSeq = 0
7
+
8
+ interface Props {
9
+ /** Identifiant de l'item (lié au v-model de l'accordéon) */
10
+ value: string
11
+ }
12
+
13
+ const props = defineProps<Props>()
14
+
15
+ const uid = `q-acc-${itemSeq++}`
16
+
17
+ provide<AccordionItemContext>(qAccordionItemKey, { value: props.value, uid })
18
+ </script>
19
+
20
+ <template>
21
+ <div class="q-accordion__item">
22
+ <slot />
23
+ </div>
24
+ </template>
@@ -0,0 +1,51 @@
1
+ <script setup lang="ts">
2
+ // QAccordionTrigger — bouton d'ouverture (équivalent AccordionTrigger).
3
+ import { computed, inject } from "vue"
4
+ import { Icon } from "@iconify/vue"
5
+ import { icons } from "../lib/icons"
6
+ import { qAccordionItemKey, qAccordionKey } from "./QAccordion.vue"
7
+
8
+ interface Props {
9
+ label?: string
10
+ /** Icône Iconify du chevron (défaut : lucide:chevron-down) */
11
+ expandIcon?: string
12
+ disable?: boolean
13
+ }
14
+
15
+ const props = withDefaults(defineProps<Props>(), {
16
+ disable: false,
17
+ })
18
+
19
+ const accordion = inject(qAccordionKey, null)
20
+ const item = inject(qAccordionItemKey, null)
21
+
22
+ const isOpen = computed(() => accordion?.isOpen(item?.value ?? "") ?? false)
23
+
24
+ const toggle = () => {
25
+ if (props.disable || !item) return
26
+ accordion?.toggle(item.value)
27
+ }
28
+ </script>
29
+
30
+ <template>
31
+ <button
32
+ type="button"
33
+ class="q-accordion__trigger"
34
+ :class="{ 'q-accordion__trigger--open': isOpen }"
35
+ :disabled="disable"
36
+ :aria-expanded="isOpen ? 'true' : 'false'"
37
+ :aria-controls="item?.uid"
38
+ @click="toggle"
39
+ >
40
+ <span class="q-accordion__trigger-content">
41
+ <span v-if="label" class="q-accordion__trigger-label">{{ label }}</span>
42
+ <slot />
43
+ </span>
44
+ <Icon
45
+ :icon="expandIcon || icons.chevronDown"
46
+ class="q-accordion__trigger-icon"
47
+ :class="{ 'q-accordion__trigger-icon--rotated': isOpen }"
48
+ aria-hidden="true"
49
+ />
50
+ </button>
51
+ </template>
@@ -0,0 +1,159 @@
1
+ <script lang="ts">
2
+ // QActionSheet — action sheet type iOS : <q-action-sheet v-model="open" :options="opts" @select="onSelect" />
3
+ // Options passées en props, événement select à la sélection (ferme puis émet).
4
+
5
+ export interface ActionSheetOption {
6
+ /** Libellé affiché */
7
+ label: string
8
+ /** Valeur émise par @select ; si absente, l'option elle-même est émise */
9
+ value?: any
10
+ /** Icône Iconify à gauche (ex. : "lucide:star") */
11
+ icon?: string
12
+ /** Icône Iconify à droite */
13
+ iconRight?: string
14
+ /** Couleur du texte (token ou hex) */
15
+ color?: string
16
+ /** Sous-texte descriptif */
17
+ description?: string
18
+ }
19
+ </script>
20
+
21
+ <script setup lang="ts">
22
+ import { computed, onBeforeUnmount, onMounted, watch } from "vue"
23
+ import { Icon } from "@iconify/vue"
24
+ import { colorValue } from "../lib/colors"
25
+ import { useOverlayBack } from "../lib/overlayBack"
26
+
27
+ interface Props {
28
+ /** Ouvert (v-model) */
29
+ modelValue?: boolean
30
+ /** Options de l'action sheet */
31
+ options?: ActionSheetOption[]
32
+ /** Titre discret au-dessus des options */
33
+ title?: string
34
+ /** Bouton Annuler : false pour masquer, string pour le libellé */
35
+ cancel?: boolean | string
36
+ /** Ne se ferme ni au backdrop ni à Échap */
37
+ persistent?: boolean
38
+ dark?: boolean
39
+ }
40
+
41
+ const props = withDefaults(defineProps<Props>(), {
42
+ modelValue: false,
43
+ options: () => [],
44
+ cancel: true,
45
+ persistent: false,
46
+ dark: false,
47
+ })
48
+
49
+ const emit = defineEmits<{
50
+ "update:modelValue": [value: boolean]
51
+ /** Valeur de l'option sélectionnée (ou l'option si pas de value) */
52
+ select: [value: any]
53
+ /** Fermeture sans sélection (backdrop, Échap, Annuler) */
54
+ cancel: []
55
+ }>()
56
+
57
+ const open = computed({
58
+ get: () => props.modelValue,
59
+ set: (v) => emit("update:modelValue", v),
60
+ })
61
+
62
+ // « Retour » navigateur → ferme l'action sheet au lieu de naviguer
63
+ useOverlayBack(open, () => { open.value = false }, "QActionSheet")
64
+
65
+ const cancelLabel = computed(() => (typeof props.cancel === "string" ? props.cancel : "Annuler"))
66
+
67
+ // Échap + verrouillage du scroll du body
68
+ const onDocKeydown = (e: KeyboardEvent) => {
69
+ if (e.key === "Escape" && open.value && !props.persistent) dismiss()
70
+ }
71
+
72
+ watch(open, (v) => {
73
+ if (typeof document !== "undefined") document.body.style.overflow = v ? "hidden" : ""
74
+ })
75
+
76
+ onMounted(() => {
77
+ if (typeof document !== "undefined") document.addEventListener("keydown", onDocKeydown)
78
+ })
79
+ onBeforeUnmount(() => {
80
+ if (typeof document !== "undefined") {
81
+ document.removeEventListener("keydown", onDocKeydown)
82
+ document.body.style.overflow = ""
83
+ }
84
+ })
85
+
86
+ const onSelect = (opt: ActionSheetOption) => {
87
+ open.value = false
88
+ emit("select", opt.value !== undefined ? opt.value : opt)
89
+ }
90
+
91
+ const dismiss = () => {
92
+ open.value = false
93
+ emit("cancel")
94
+ }
95
+
96
+ const onOverlayClick = () => {
97
+ if (!props.persistent) dismiss()
98
+ }
99
+
100
+ const getKey = (opt: ActionSheetOption, i: number) => String(opt.value ?? `opt-${i}`)
101
+
102
+ const optionStyle = (opt: ActionSheetOption) =>
103
+ opt.color ? { color: colorValue(opt.color) } : undefined
104
+
105
+ const panelClasses = computed(() => [
106
+ "q-action-sheet__panel",
107
+ props.dark && "q-action-sheet__panel--dark",
108
+ ])
109
+ </script>
110
+
111
+ <template>
112
+ <Teleport to="body">
113
+ <Transition name="q-bs">
114
+ <div
115
+ v-if="open"
116
+ class="q-action-sheet__overlay"
117
+ @click="onOverlayClick"
118
+ >
119
+ <div
120
+ class="q-action-sheet__panel"
121
+ :class="panelClasses"
122
+ role="dialog"
123
+ aria-modal="true"
124
+ @click.stop
125
+ >
126
+ <h2 v-if="title" class="q-action-sheet__title">{{ title }}</h2>
127
+
128
+ <div class="q-action-sheet__options" role="listbox">
129
+ <button
130
+ v-for="(opt, i) in options"
131
+ :key="getKey(opt, i)"
132
+ type="button"
133
+ role="option"
134
+ class="q-action-sheet__option"
135
+ :style="optionStyle(opt)"
136
+ @click="onSelect(opt)"
137
+ >
138
+ <Icon :icon="opt.icon" v-if="opt.icon" class="q-action-sheet__option-icon" aria-hidden="true" />
139
+ <span class="q-action-sheet__option-text">
140
+ <span class="q-action-sheet__option-label">{{ opt.label }}</span>
141
+ <span v-if="opt.description" class="q-action-sheet__option-description">{{ opt.description }}</span>
142
+ </span>
143
+ <Icon :icon="opt.iconRight" v-if="opt.iconRight" class="q-action-sheet__option-icon" aria-hidden="true" />
144
+ </button>
145
+ </div>
146
+
147
+ <button
148
+ v-if="cancel !== false"
149
+ type="button"
150
+ class="q-action-sheet__cancel"
151
+ @click="dismiss"
152
+ >
153
+ {{ cancelLabel }}
154
+ </button>
155
+ </div>
156
+ </div>
157
+ </Transition>
158
+ </Teleport>
159
+ </template>
@@ -0,0 +1,8 @@
1
+ <template>
2
+ <div class="q-app">
3
+ <slot></slot>
4
+ </div>
5
+ </template>
6
+ <script setup>
7
+
8
+ </script>