@birdycom/omniaui-vue 0.11.0 → 0.11.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 (178) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +49 -49
  3. package/dist/omniaui-vue.js.map +1 -1
  4. package/package.json +69 -69
  5. package/src/blocks/OcBlockAboutTimeline.vue +44 -44
  6. package/src/blocks/OcBlockAppHeader.vue +36 -36
  7. package/src/blocks/OcBlockAppShell.vue +29 -29
  8. package/src/blocks/OcBlockAuth.vue +24 -24
  9. package/src/blocks/OcBlockAuthSplit.vue +47 -47
  10. package/src/blocks/OcBlockContactGrid.vue +53 -53
  11. package/src/blocks/OcBlockCta.vue +12 -12
  12. package/src/blocks/OcBlockDataTable.vue +27 -27
  13. package/src/blocks/OcBlockFaq.vue +49 -49
  14. package/src/blocks/OcBlockFeatures.vue +23 -23
  15. package/src/blocks/OcBlockFooter.vue +25 -25
  16. package/src/blocks/OcBlockFormPage.vue +24 -24
  17. package/src/blocks/OcBlockHero.vue +13 -13
  18. package/src/blocks/OcBlockHeroCode.vue +42 -42
  19. package/src/blocks/OcBlockHeroOrbit.vue +69 -69
  20. package/src/blocks/OcBlockHeroSplit.vue +15 -15
  21. package/src/blocks/OcBlockModuleHeader.vue +21 -21
  22. package/src/blocks/OcBlockPageHero.vue +13 -13
  23. package/src/blocks/OcBlockPortfolioGrid.vue +63 -63
  24. package/src/blocks/OcBlockPricing.vue +39 -39
  25. package/src/blocks/OcBlockProcess.vue +39 -39
  26. package/src/blocks/OcBlockProductGrid.vue +41 -41
  27. package/src/blocks/OcBlockProfileHeader.vue +50 -50
  28. package/src/blocks/OcBlockShowcase.vue +43 -43
  29. package/src/blocks/OcBlockSiteFooter.vue +54 -54
  30. package/src/blocks/OcBlockSiteHeader.vue +34 -34
  31. package/src/blocks/OcBlockSpotlight.vue +47 -47
  32. package/src/blocks/OcBlockStats.vue +17 -17
  33. package/src/blocks/OcBlockStatsCounter.vue +20 -20
  34. package/src/blocks/OcBlockTeamList.vue +53 -53
  35. package/src/blocks/OcBlockTwoFactor.vue +61 -61
  36. package/src/blocks/OcBlockWizardDialog.vue +67 -67
  37. package/src/components/OcAccordion.vue +12 -12
  38. package/src/components/OcAccordionAccent.vue +27 -27
  39. package/src/components/OcAccordionItem.vue +19 -19
  40. package/src/components/OcAffixInput.vue +40 -40
  41. package/src/components/OcAlert.vue +17 -17
  42. package/src/components/OcAlertDialog.vue +66 -66
  43. package/src/components/OcAlphaTabs.vue +54 -54
  44. package/src/components/OcAspectRatio.vue +21 -21
  45. package/src/components/OcAttachment.vue +59 -59
  46. package/src/components/OcAttachmentImage.vue +13 -13
  47. package/src/components/OcAttachmentList.vue +31 -31
  48. package/src/components/OcAttachmentThumb.vue +14 -14
  49. package/src/components/OcAvatar.vue +18 -18
  50. package/src/components/OcAvatarGroup.vue +7 -7
  51. package/src/components/OcBackLink.vue +8 -8
  52. package/src/components/OcBadge.vue +13 -13
  53. package/src/components/OcBarcodeInput.vue +51 -51
  54. package/src/components/OcBreadcrumb.vue +22 -22
  55. package/src/components/OcBrowserFrame.vue +33 -33
  56. package/src/components/OcBusyOverlay.vue +32 -32
  57. package/src/components/OcButton.vue +47 -47
  58. package/src/components/OcButtonGroup.vue +10 -10
  59. package/src/components/OcButtonGroupText.vue +7 -7
  60. package/src/components/OcCard.vue +20 -20
  61. package/src/components/OcChartLine.vue +80 -80
  62. package/src/components/OcChatComposer.vue +42 -42
  63. package/src/components/OcCheckbox.vue +26 -26
  64. package/src/components/OcChecklist.vue +29 -29
  65. package/src/components/OcCollapsible.vue +19 -19
  66. package/src/components/OcColorField.vue +15 -15
  67. package/src/components/OcColorSelect.vue +33 -33
  68. package/src/components/OcColumnMenu.vue +50 -50
  69. package/src/components/OcCommand.vue +119 -119
  70. package/src/components/OcConfirmDialog.vue +65 -65
  71. package/src/components/OcCookieConsent.vue +119 -119
  72. package/src/components/OcCopyField.vue +37 -37
  73. package/src/components/OcCounter.vue +15 -15
  74. package/src/components/OcDataTable.vue +144 -144
  75. package/src/components/OcDefinitionList.vue +35 -35
  76. package/src/components/OcDropdown.vue +23 -23
  77. package/src/components/OcDropdownItem.vue +9 -9
  78. package/src/components/OcDropdownLabel.vue +7 -7
  79. package/src/components/OcDropdownSeparator.vue +7 -7
  80. package/src/components/OcDropzone.vue +36 -36
  81. package/src/components/OcEmojiPicker.vue +45 -45
  82. package/src/components/OcEmptyState.vue +13 -13
  83. package/src/components/OcEntityCard.vue +47 -47
  84. package/src/components/OcFactList.vue +37 -37
  85. package/src/components/OcFilterCounts.vue +38 -38
  86. package/src/components/OcFlipCard.vue +36 -36
  87. package/src/components/OcFormField.vue +36 -36
  88. package/src/components/OcGreeting.vue +52 -52
  89. package/src/components/OcHeading.vue +19 -19
  90. package/src/components/OcHoverCard.vue +25 -25
  91. package/src/components/OcImageZoom.vue +39 -39
  92. package/src/components/OcInput.vue +9 -9
  93. package/src/components/OcInputGroup.vue +12 -12
  94. package/src/components/OcItem.vue +40 -40
  95. package/src/components/OcItemGroup.vue +7 -7
  96. package/src/components/OcItemSeparator.vue +7 -7
  97. package/src/components/OcKbd.vue +7 -7
  98. package/src/components/OcKbdGroup.vue +15 -15
  99. package/src/components/OcLabel.vue +10 -10
  100. package/src/components/OcLanguageSelect.vue +40 -40
  101. package/src/components/OcLauncherCard.vue +34 -34
  102. package/src/components/OcLightbox.vue +63 -63
  103. package/src/components/OcLinkArrow.vue +25 -25
  104. package/src/components/OcListToolbar.vue +44 -44
  105. package/src/components/OcMarquee.vue +36 -36
  106. package/src/components/OcMediaCard.vue +28 -28
  107. package/src/components/OcMediaRow.vue +28 -28
  108. package/src/components/OcMediaThumb.vue +38 -38
  109. package/src/components/OcMessage.vue +91 -91
  110. package/src/components/OcMessageList.vue +43 -43
  111. package/src/components/OcMessageThread.vue +155 -155
  112. package/src/components/OcModal.vue +42 -42
  113. package/src/components/OcNavmenu.vue +18 -18
  114. package/src/components/OcNavmenuList.vue +38 -38
  115. package/src/components/OcNextTeaser.vue +25 -25
  116. package/src/components/OcNumberInput.vue +47 -47
  117. package/src/components/OcOtpInput.vue +34 -34
  118. package/src/components/OcPageHeader.vue +34 -34
  119. package/src/components/OcPagination.vue +33 -33
  120. package/src/components/OcPasswordInput.vue +27 -27
  121. package/src/components/OcPasswordRequirements.vue +28 -28
  122. package/src/components/OcPhoneInput.vue +72 -72
  123. package/src/components/OcPopover.vue +25 -25
  124. package/src/components/OcPriceCard.vue +69 -69
  125. package/src/components/OcProductMark.vue +31 -31
  126. package/src/components/OcProgress.vue +21 -21
  127. package/src/components/OcProjectCard.vue +36 -36
  128. package/src/components/OcProse.vue +57 -57
  129. package/src/components/OcRadio.vue +40 -40
  130. package/src/components/OcRadioGroup.vue +32 -32
  131. package/src/components/OcRecoveryCodes.vue +55 -55
  132. package/src/components/OcScrollArea.vue +15 -15
  133. package/src/components/OcSegmented.vue +28 -28
  134. package/src/components/OcSelect.vue +21 -21
  135. package/src/components/OcSeparator.vue +18 -18
  136. package/src/components/OcSeverityCard.vue +46 -46
  137. package/src/components/OcSheet.vue +49 -49
  138. package/src/components/OcSidebarCollapsible.vue +19 -19
  139. package/src/components/OcSidebarGroup.vue +11 -11
  140. package/src/components/OcSidebarMenu.vue +7 -7
  141. package/src/components/OcSidebarMenuButton.vue +31 -31
  142. package/src/components/OcSidebarSeparator.vue +7 -7
  143. package/src/components/OcSkeleton.vue +8 -8
  144. package/src/components/OcSlider.vue +27 -27
  145. package/src/components/OcSortableRow.vue +40 -40
  146. package/src/components/OcSpinner.vue +13 -13
  147. package/src/components/OcStackCard.vue +24 -24
  148. package/src/components/OcStackList.vue +31 -31
  149. package/src/components/OcStatCard.vue +39 -39
  150. package/src/components/OcStepper.vue +34 -34
  151. package/src/components/OcSwitch.vue +15 -15
  152. package/src/components/OcTable.vue +115 -115
  153. package/src/components/OcTableActions.vue +26 -26
  154. package/src/components/OcTableCompact.vue +46 -46
  155. package/src/components/OcTabs.vue +37 -37
  156. package/src/components/OcTagInput.vue +50 -50
  157. package/src/components/OcTerminalLog.vue +50 -50
  158. package/src/components/OcTextarea.vue +9 -9
  159. package/src/components/OcThemeSwitch.vue +31 -31
  160. package/src/components/OcTimeInput.vue +50 -50
  161. package/src/components/OcTimeline.vue +36 -36
  162. package/src/components/OcToast.vue +31 -31
  163. package/src/components/OcToastContainer.vue +21 -21
  164. package/src/components/OcToggle.vue +63 -63
  165. package/src/components/OcToggleField.vue +28 -28
  166. package/src/components/OcToggleGroup.vue +40 -40
  167. package/src/components/OcTooltip.vue +8 -8
  168. package/src/components/OcTopProgress.vue +54 -54
  169. package/src/components/OcTree.vue +70 -70
  170. package/src/components/OcUpgradeBanner.vue +42 -42
  171. package/src/components/OcUser.vue +25 -25
  172. package/src/components/OcVersionBanner.vue +34 -34
  173. package/src/composables/chartLine.ts +28 -28
  174. package/src/composables/keys.ts +22 -22
  175. package/src/composables/useAttrsSplit.ts +16 -16
  176. package/src/composables/useDialog.ts +21 -21
  177. package/src/composables/useToast.ts +66 -66
  178. package/src/composables/useUid.ts +12 -12
@@ -1,28 +1,28 @@
1
- // File: packages/vue/src/composables/chartLine.ts
2
- // Map: number format -> nice axis maximum -> smooth path (same geometry as the chart-line snippet and the React wrapper)
3
-
4
- /** Number with at most 2 decimals and no trailing zeros ("75", "37.5", "4.69"). */
5
- export const n2 = (n: number) => String(parseFloat(n.toFixed(2)))
6
-
7
- /** Round axis maximum: step = max / rows rounded up to 1, 1.5, 2, 2.5, 3, 4, 5, 6, 8 or 10 x 10^k. */
8
- export function niceMax(value: number, rows = 4) {
9
- if (value <= 0) return rows
10
- const raw = value / rows
11
- const pow = 10 ** Math.floor(Math.log10(raw))
12
- return ([1, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10].find((s) => s * pow >= raw) ?? 10) * pow * rows
13
- }
14
-
15
- /** Smooth path through the points (x 0-100, y = 100 - value / max * 100); control points stay between their two ends. */
16
- export function chartLinePath(values: number[], max: number) {
17
- const pts = values.map((v, i) => [values.length > 1 ? (i / (values.length - 1)) * 100 : 50, 100 - (v / max) * 100])
18
- if (!pts.length) return ''
19
- const clamp = (v: number, a: number, b: number) => Math.min(Math.max(v, Math.min(a, b)), Math.max(a, b))
20
- let d = `M${n2(pts[0][0])} ${n2(pts[0][1])}`
21
- for (let i = 0; i < pts.length - 1; i++) {
22
- const p0 = pts[i - 1] ?? pts[i], p1 = pts[i], p2 = pts[i + 1], p3 = pts[i + 2] ?? p2
23
- const c1 = [p1[0] + (p2[0] - p0[0]) / 6, clamp(p1[1] + (p2[1] - p0[1]) / 6, p1[1], p2[1])]
24
- const c2 = [p2[0] - (p3[0] - p1[0]) / 6, clamp(p2[1] - (p3[1] - p1[1]) / 6, p1[1], p2[1])]
25
- d += ` C${n2(c1[0])} ${n2(c1[1])} ${n2(c2[0])} ${n2(c2[1])} ${n2(p2[0])} ${n2(p2[1])}`
26
- }
27
- return d
28
- }
1
+ // File: packages/vue/src/composables/chartLine.ts
2
+ // Map: number format -> nice axis maximum -> smooth path (same geometry as the chart-line snippet and the React wrapper)
3
+
4
+ /** Number with at most 2 decimals and no trailing zeros ("75", "37.5", "4.69"). */
5
+ export const n2 = (n: number) => String(parseFloat(n.toFixed(2)))
6
+
7
+ /** Round axis maximum: step = max / rows rounded up to 1, 1.5, 2, 2.5, 3, 4, 5, 6, 8 or 10 x 10^k. */
8
+ export function niceMax(value: number, rows = 4) {
9
+ if (value <= 0) return rows
10
+ const raw = value / rows
11
+ const pow = 10 ** Math.floor(Math.log10(raw))
12
+ return ([1, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10].find((s) => s * pow >= raw) ?? 10) * pow * rows
13
+ }
14
+
15
+ /** Smooth path through the points (x 0-100, y = 100 - value / max * 100); control points stay between their two ends. */
16
+ export function chartLinePath(values: number[], max: number) {
17
+ const pts = values.map((v, i) => [values.length > 1 ? (i / (values.length - 1)) * 100 : 50, 100 - (v / max) * 100])
18
+ if (!pts.length) return ''
19
+ const clamp = (v: number, a: number, b: number) => Math.min(Math.max(v, Math.min(a, b)), Math.max(a, b))
20
+ let d = `M${n2(pts[0][0])} ${n2(pts[0][1])}`
21
+ for (let i = 0; i < pts.length - 1; i++) {
22
+ const p0 = pts[i - 1] ?? pts[i], p1 = pts[i], p2 = pts[i + 1], p3 = pts[i + 2] ?? p2
23
+ const c1 = [p1[0] + (p2[0] - p0[0]) / 6, clamp(p1[1] + (p2[1] - p0[1]) / 6, p1[1], p2[1])]
24
+ const c2 = [p2[0] - (p3[0] - p1[0]) / 6, clamp(p2[1] - (p3[1] - p1[1]) / 6, p1[1], p2[1])]
25
+ d += ` C${n2(c1[0])} ${n2(c1[1])} ${n2(c2[0])} ${n2(c2[1])} ${n2(p2[0])} ${n2(p2[1])}`
26
+ }
27
+ return d
28
+ }
@@ -1,22 +1,22 @@
1
- import type { InjectionKey, Ref } from 'vue'
2
-
3
- /** Provided by OcRadioGroup, injected by OcRadio. */
4
- export interface RadioGroupContext {
5
- model: Ref<string | number | undefined>
6
- name: Ref<string>
7
- card: Ref<boolean>
8
- }
9
- export const radioGroupKey: InjectionKey<RadioGroupContext> = Symbol('oc-radio-group')
10
-
11
- /** Provided by OcToggleGroup, injected by OcToggle. */
12
- export interface ToggleGroupContext {
13
- /** Currently pressed values. */
14
- values: Ref<string[]>
15
- type: Ref<'single' | 'multiple'>
16
- name: Ref<string>
17
- toggle: (value: string) => void
18
- }
19
- export const toggleGroupKey: InjectionKey<ToggleGroupContext> = Symbol('oc-toggle-group')
20
-
21
- /** Provided by OcResizable, injected by OcResizablePanel. */
22
- export const resizableVerticalKey: InjectionKey<Ref<boolean>> = Symbol('oc-resizable-vertical')
1
+ import type { InjectionKey, Ref } from 'vue'
2
+
3
+ /** Provided by OcRadioGroup, injected by OcRadio. */
4
+ export interface RadioGroupContext {
5
+ model: Ref<string | number | undefined>
6
+ name: Ref<string>
7
+ card: Ref<boolean>
8
+ }
9
+ export const radioGroupKey: InjectionKey<RadioGroupContext> = Symbol('oc-radio-group')
10
+
11
+ /** Provided by OcToggleGroup, injected by OcToggle. */
12
+ export interface ToggleGroupContext {
13
+ /** Currently pressed values. */
14
+ values: Ref<string[]>
15
+ type: Ref<'single' | 'multiple'>
16
+ name: Ref<string>
17
+ toggle: (value: string) => void
18
+ }
19
+ export const toggleGroupKey: InjectionKey<ToggleGroupContext> = Symbol('oc-toggle-group')
20
+
21
+ /** Provided by OcResizable, injected by OcResizablePanel. */
22
+ export const resizableVerticalKey: InjectionKey<Ref<boolean>> = Symbol('oc-resizable-vertical')
@@ -1,16 +1,16 @@
1
- import { computed, useAttrs } from 'vue'
2
-
3
- /**
4
- * For components whose root is a wrapper (label, div) around the real form control:
5
- * `class` and `style` stay on the wrapper, every other attribute (id, name, disabled,
6
- * autocomplete, aria-*, listeners) goes to the control. Use with defineOptions({ inheritAttrs: false }).
7
- */
8
- export function useAttrsSplit() {
9
- const attrs = useAttrs()
10
- const root = computed(() => ({ class: attrs.class, style: attrs.style }))
11
- const control = computed(() => {
12
- const { class: _c, style: _s, ...rest } = attrs
13
- return rest
14
- })
15
- return { root, control }
16
- }
1
+ import { computed, useAttrs } from 'vue'
2
+
3
+ /**
4
+ * For components whose root is a wrapper (label, div) around the real form control:
5
+ * `class` and `style` stay on the wrapper, every other attribute (id, name, disabled,
6
+ * autocomplete, aria-*, listeners) goes to the control. Use with defineOptions({ inheritAttrs: false }).
7
+ */
8
+ export function useAttrsSplit() {
9
+ const attrs = useAttrs()
10
+ const root = computed(() => ({ class: attrs.class, style: attrs.style }))
11
+ const control = computed(() => {
12
+ const { class: _c, style: _s, ...rest } = attrs
13
+ return rest
14
+ })
15
+ return { root, control }
16
+ }
@@ -1,21 +1,21 @@
1
- import { onMounted, watch, type Ref } from 'vue'
2
-
3
- /**
4
- * Keeps a native <dialog> in sync with a boolean `open` model:
5
- * open -> showModal(), closed -> close(). Native close (Esc, backdrop, form method=dialog)
6
- * is reported through `onClose` so v-model:open stays correct.
7
- */
8
- export function useDialog(open: Ref<boolean | undefined>, el: Ref<HTMLDialogElement | null>) {
9
- function sync() {
10
- const dialog = el.value
11
- if (!dialog) return
12
- if (open.value && !dialog.open) dialog.showModal()
13
- else if (!open.value && dialog.open) dialog.close()
14
- }
15
- watch(open, sync, { flush: 'post' })
16
- onMounted(sync)
17
- function onClose() {
18
- if (open.value) open.value = false
19
- }
20
- return { onClose }
21
- }
1
+ import { onMounted, watch, type Ref } from 'vue'
2
+
3
+ /**
4
+ * Keeps a native <dialog> in sync with a boolean `open` model:
5
+ * open -> showModal(), closed -> close(). Native close (Esc, backdrop, form method=dialog)
6
+ * is reported through `onClose` so v-model:open stays correct.
7
+ */
8
+ export function useDialog(open: Ref<boolean | undefined>, el: Ref<HTMLDialogElement | null>) {
9
+ function sync() {
10
+ const dialog = el.value
11
+ if (!dialog) return
12
+ if (open.value && !dialog.open) dialog.showModal()
13
+ else if (!open.value && dialog.open) dialog.close()
14
+ }
15
+ watch(open, sync, { flush: 'post' })
16
+ onMounted(sync)
17
+ function onClose() {
18
+ if (open.value) open.value = false
19
+ }
20
+ return { onClose }
21
+ }
@@ -1,66 +1,66 @@
1
- import { reactive, readonly } from 'vue'
2
-
3
- export type ToastVariant = 'success' | 'error' | 'warning' | 'info'
4
-
5
- export interface ToastOptions {
6
- title: string
7
- description?: string
8
- variant?: ToastVariant
9
- /** Milliseconds before auto-dismiss. 0 keeps the toast until dismissed. Default 5000. */
10
- duration?: number
11
- }
12
-
13
- export interface ToastItem extends Required<Pick<ToastOptions, 'title' | 'variant'>> {
14
- id: number
15
- description?: string
16
- duration: number
17
- }
18
-
19
- const state = reactive<{ toasts: ToastItem[] }>({ toasts: [] })
20
- const timers = new Map<number, ReturnType<typeof setTimeout>>()
21
- let nextId = 1
22
-
23
- function dismiss(id: number) {
24
- const timer = timers.get(id)
25
- if (timer) clearTimeout(timer)
26
- timers.delete(id)
27
- const i = state.toasts.findIndex((t) => t.id === id)
28
- if (i !== -1) state.toasts.splice(i, 1)
29
- }
30
-
31
- function push(options: ToastOptions): number {
32
- const id = nextId++
33
- const item: ToastItem = {
34
- id,
35
- title: options.title,
36
- description: options.description,
37
- variant: options.variant ?? 'info',
38
- duration: options.duration ?? 5000,
39
- }
40
- state.toasts.push(item)
41
- if (item.duration > 0) timers.set(id, setTimeout(() => dismiss(id), item.duration))
42
- return id
43
- }
44
-
45
- function clear() {
46
- for (const t of [...state.toasts]) dismiss(t.id)
47
- }
48
-
49
- const shortcut =
50
- (variant: ToastVariant) =>
51
- (title: string, description?: string, options: Omit<ToastOptions, 'title' | 'description' | 'variant'> = {}) =>
52
- push({ ...options, title, description, variant })
53
-
54
- /** Shared toast queue. Render it once with <OcToastContainer />. */
55
- export function useToast() {
56
- return {
57
- toasts: readonly(state).toasts,
58
- push,
59
- dismiss,
60
- clear,
61
- success: shortcut('success'),
62
- error: shortcut('error'),
63
- warning: shortcut('warning'),
64
- info: shortcut('info'),
65
- }
66
- }
1
+ import { reactive, readonly } from 'vue'
2
+
3
+ export type ToastVariant = 'success' | 'error' | 'warning' | 'info'
4
+
5
+ export interface ToastOptions {
6
+ title: string
7
+ description?: string
8
+ variant?: ToastVariant
9
+ /** Milliseconds before auto-dismiss. 0 keeps the toast until dismissed. Default 5000. */
10
+ duration?: number
11
+ }
12
+
13
+ export interface ToastItem extends Required<Pick<ToastOptions, 'title' | 'variant'>> {
14
+ id: number
15
+ description?: string
16
+ duration: number
17
+ }
18
+
19
+ const state = reactive<{ toasts: ToastItem[] }>({ toasts: [] })
20
+ const timers = new Map<number, ReturnType<typeof setTimeout>>()
21
+ let nextId = 1
22
+
23
+ function dismiss(id: number) {
24
+ const timer = timers.get(id)
25
+ if (timer) clearTimeout(timer)
26
+ timers.delete(id)
27
+ const i = state.toasts.findIndex((t) => t.id === id)
28
+ if (i !== -1) state.toasts.splice(i, 1)
29
+ }
30
+
31
+ function push(options: ToastOptions): number {
32
+ const id = nextId++
33
+ const item: ToastItem = {
34
+ id,
35
+ title: options.title,
36
+ description: options.description,
37
+ variant: options.variant ?? 'info',
38
+ duration: options.duration ?? 5000,
39
+ }
40
+ state.toasts.push(item)
41
+ if (item.duration > 0) timers.set(id, setTimeout(() => dismiss(id), item.duration))
42
+ return id
43
+ }
44
+
45
+ function clear() {
46
+ for (const t of [...state.toasts]) dismiss(t.id)
47
+ }
48
+
49
+ const shortcut =
50
+ (variant: ToastVariant) =>
51
+ (title: string, description?: string, options: Omit<ToastOptions, 'title' | 'description' | 'variant'> = {}) =>
52
+ push({ ...options, title, description, variant })
53
+
54
+ /** Shared toast queue. Render it once with <OcToastContainer />. */
55
+ export function useToast() {
56
+ return {
57
+ toasts: readonly(state).toasts,
58
+ push,
59
+ dismiss,
60
+ clear,
61
+ success: shortcut('success'),
62
+ error: shortcut('error'),
63
+ warning: shortcut('warning'),
64
+ info: shortcut('info'),
65
+ }
66
+ }
@@ -1,12 +1,12 @@
1
- import * as Vue from 'vue'
2
-
3
- let counter = 0
4
-
5
- /**
6
- * Stable unique id for aria-labelledby / popovertarget / label-for wiring.
7
- * Uses Vue's built-in useId() when available (Vue >= 3.5, SSR safe), otherwise a counter.
8
- */
9
- export function useUid(prefix = 'oc'): string {
10
- const useId = (Vue as Record<string, unknown>)['useId'] as (() => string) | undefined
11
- return `${prefix}-${useId ? useId() : ++counter}`
12
- }
1
+ import * as Vue from 'vue'
2
+
3
+ let counter = 0
4
+
5
+ /**
6
+ * Stable unique id for aria-labelledby / popovertarget / label-for wiring.
7
+ * Uses Vue's built-in useId() when available (Vue >= 3.5, SSR safe), otherwise a counter.
8
+ */
9
+ export function useUid(prefix = 'oc'): string {
10
+ const useId = (Vue as Record<string, unknown>)['useId'] as (() => string) | undefined
11
+ return `${prefix}-${useId ? useId() : ++counter}`
12
+ }