@birdycom/omniaui-vue 0.11.0 → 0.11.2

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,31 +1,31 @@
1
- <script setup lang="ts">
2
- /**
3
- * Sidebar item: <a> with `href`, otherwise <button>. State: `current` (aria-current="page"), `disabled`.
4
- * Slots: icon (inline svg with class oc-sidebar-menu-icon), default (label). `badge` shows a count pill.
5
- */
6
- import { computed } from 'vue'
7
-
8
- const props = defineProps<{
9
- href?: string
10
- current?: boolean
11
- disabled?: boolean
12
- large?: boolean
13
- badge?: string | number
14
- }>()
15
- const tag = computed(() => (props.href ? 'a' : 'button'))
16
- </script>
17
-
18
- <template>
19
- <component
20
- :is="tag"
21
- :class="['oc-sidebar-menu-button', large && 'oc-sidebar-menu-button--lg']"
22
- :href="href"
23
- :type="tag === 'button' ? 'button' : undefined"
24
- :aria-current="current ? 'page' : undefined"
25
- :aria-disabled="disabled ? 'true' : undefined"
26
- >
27
- <slot name="icon" />
28
- <span class="oc-sidebar-menu-label"><slot /></span>
29
- <span v-if="badge !== undefined" class="oc-sidebar-menu-badge">{{ badge }}</span>
30
- </component>
31
- </template>
1
+ <script setup lang="ts">
2
+ /**
3
+ * Sidebar item: <a> with `href`, otherwise <button>. State: `current` (aria-current="page"), `disabled`.
4
+ * Slots: icon (inline svg with class oc-sidebar-menu-icon), default (label). `badge` shows a count pill.
5
+ */
6
+ import { computed } from 'vue'
7
+
8
+ const props = defineProps<{
9
+ href?: string
10
+ current?: boolean
11
+ disabled?: boolean
12
+ large?: boolean
13
+ badge?: string | number
14
+ }>()
15
+ const tag = computed(() => (props.href ? 'a' : 'button'))
16
+ </script>
17
+
18
+ <template>
19
+ <component
20
+ :is="tag"
21
+ :class="['oc-sidebar-menu-button', large && 'oc-sidebar-menu-button--lg']"
22
+ :href="href"
23
+ :type="tag === 'button' ? 'button' : undefined"
24
+ :aria-current="current ? 'page' : undefined"
25
+ :aria-disabled="disabled ? 'true' : undefined"
26
+ >
27
+ <slot name="icon" />
28
+ <span class="oc-sidebar-menu-label"><slot /></span>
29
+ <span v-if="badge !== undefined" class="oc-sidebar-menu-badge">{{ badge }}</span>
30
+ </component>
31
+ </template>
@@ -1,7 +1,7 @@
1
- <script setup lang="ts">
2
- /** Divider line between sidebar groups. */
3
- </script>
4
-
5
- <template>
6
- <div class="oc-sidebar-separator"></div>
7
- </template>
1
+ <script setup lang="ts">
2
+ /** Divider line between sidebar groups. */
3
+ </script>
4
+
5
+ <template>
6
+ <div class="oc-sidebar-separator"></div>
7
+ </template>
@@ -1,8 +1,8 @@
1
- <script setup lang="ts">
2
- /** Loading skeleton. Classes: .oc-skeleton--circle/rect/text/title */
3
- withDefaults(defineProps<{ variant?: 'text' | 'title' | 'circle' | 'rect' }>(), { variant: 'text' })
4
- </script>
5
-
6
- <template>
7
- <div :class="['oc-skeleton', `oc-skeleton--${variant}`]"></div>
8
- </template>
1
+ <script setup lang="ts">
2
+ /** Loading skeleton. Classes: .oc-skeleton--circle/rect/text/title */
3
+ withDefaults(defineProps<{ variant?: 'text' | 'title' | 'circle' | 'rect' }>(), { variant: 'text' })
4
+ </script>
5
+
6
+ <template>
7
+ <div :class="['oc-skeleton', `oc-skeleton--${variant}`]"></div>
8
+ </template>
@@ -1,27 +1,27 @@
1
- <script setup lang="ts">
2
- /**
3
- * Native range input. v-model: number. Keeps --oc-slider-progress in sync (the fill for Chromium/WebKit).
4
- * Native attributes (id, aria-label, disabled...) fall through to the input. Classes: .oc-slider(--vertical)
5
- */
6
- import { computed } from 'vue'
7
-
8
- const props = withDefaults(defineProps<{ min?: number; max?: number; step?: number; vertical?: boolean }>(), { min: 0, max: 100 })
9
- const model = defineModel<number>({ default: 0 })
10
- const progress = computed(() => {
11
- const span = props.max - props.min
12
- const pct = span > 0 ? ((model.value - props.min) / span) * 100 : 0
13
- return `${Math.min(100, Math.max(0, pct))}%`
14
- })
15
- </script>
16
-
17
- <template>
18
- <input
19
- v-model.number="model"
20
- :class="['oc-slider', vertical && 'oc-slider--vertical']"
21
- type="range"
22
- :min="min"
23
- :max="max"
24
- :step="step"
25
- :style="{ '--oc-slider-progress': progress }"
26
- />
27
- </template>
1
+ <script setup lang="ts">
2
+ /**
3
+ * Native range input. v-model: number. Keeps --oc-slider-progress in sync (the fill for Chromium/WebKit).
4
+ * Native attributes (id, aria-label, disabled...) fall through to the input. Classes: .oc-slider(--vertical)
5
+ */
6
+ import { computed } from 'vue'
7
+
8
+ const props = withDefaults(defineProps<{ min?: number; max?: number; step?: number; vertical?: boolean }>(), { min: 0, max: 100 })
9
+ const model = defineModel<number>({ default: 0 })
10
+ const progress = computed(() => {
11
+ const span = props.max - props.min
12
+ const pct = span > 0 ? ((model.value - props.min) / span) * 100 : 0
13
+ return `${Math.min(100, Math.max(0, pct))}%`
14
+ })
15
+ </script>
16
+
17
+ <template>
18
+ <input
19
+ v-model.number="model"
20
+ :class="['oc-slider', vertical && 'oc-slider--vertical']"
21
+ type="range"
22
+ :min="min"
23
+ :max="max"
24
+ :step="step"
25
+ :style="{ '--oc-slider-progress': progress }"
26
+ />
27
+ </template>
@@ -1,40 +1,40 @@
1
- <!-- File: packages/vue/src/components/OcSortableRow.vue | Map: tr.oc-sortable-row -> grip cell (button) -> default slot (cells) -->
2
- <script setup lang="ts">
3
- /**
4
- * Table row with a drag grip. Styling only: listen to @dragstart / @dragover / @drop on the component
5
- * (they fall through to the <tr>) and set `dragging` / `drop` yourself. Emits `grip-keydown` for keyboard moves.
6
- * Classes: tr.oc-sortable-row(.is-dragging/.is-drop-before/.is-drop-after), td.oc-sortable-row-grip-cell, button.oc-sortable-row-grip
7
- */
8
- withDefaults(
9
- defineProps<{
10
- gripLabel: string
11
- dragging?: boolean
12
- drop?: 'before' | 'after' | null
13
- locked?: boolean
14
- /** Picked up with the keyboard (aria-pressed). Leave undefined when not used. */
15
- grabbed?: boolean
16
- }>(),
17
- // Vue casts a missing boolean prop to false; undefined keeps aria-pressed off the grip.
18
- { grabbed: undefined, drop: null },
19
- )
20
- const emit = defineEmits<{ 'grip-keydown': [e: KeyboardEvent] }>()
21
- </script>
22
-
23
- <template>
24
- <tr
25
- :class="['oc-sortable-row', dragging && 'is-dragging', drop && `is-drop-${drop}`]"
26
- :draggable="locked ? undefined : 'true'"
27
- >
28
- <td class="oc-sortable-row-grip-cell">
29
- <button
30
- class="oc-sortable-row-grip"
31
- type="button"
32
- :aria-label="gripLabel"
33
- :aria-pressed="grabbed"
34
- :disabled="locked"
35
- @keydown="emit('grip-keydown', $event)"
36
- ></button>
37
- </td>
38
- <slot />
39
- </tr>
40
- </template>
1
+ <!-- File: packages/vue/src/components/OcSortableRow.vue | Map: tr.oc-sortable-row -> grip cell (button) -> default slot (cells) -->
2
+ <script setup lang="ts">
3
+ /**
4
+ * Table row with a drag grip. Styling only: listen to @dragstart / @dragover / @drop on the component
5
+ * (they fall through to the <tr>) and set `dragging` / `drop` yourself. Emits `grip-keydown` for keyboard moves.
6
+ * Classes: tr.oc-sortable-row(.is-dragging/.is-drop-before/.is-drop-after), td.oc-sortable-row-grip-cell, button.oc-sortable-row-grip
7
+ */
8
+ withDefaults(
9
+ defineProps<{
10
+ gripLabel: string
11
+ dragging?: boolean
12
+ drop?: 'before' | 'after' | null
13
+ locked?: boolean
14
+ /** Picked up with the keyboard (aria-pressed). Leave undefined when not used. */
15
+ grabbed?: boolean
16
+ }>(),
17
+ // Vue casts a missing boolean prop to false; undefined keeps aria-pressed off the grip.
18
+ { grabbed: undefined, drop: null },
19
+ )
20
+ const emit = defineEmits<{ 'grip-keydown': [e: KeyboardEvent] }>()
21
+ </script>
22
+
23
+ <template>
24
+ <tr
25
+ :class="['oc-sortable-row', dragging && 'is-dragging', drop && `is-drop-${drop}`]"
26
+ :draggable="locked ? undefined : 'true'"
27
+ >
28
+ <td class="oc-sortable-row-grip-cell">
29
+ <button
30
+ class="oc-sortable-row-grip"
31
+ type="button"
32
+ :aria-label="gripLabel"
33
+ :aria-pressed="grabbed"
34
+ :disabled="locked"
35
+ @keydown="emit('grip-keydown', $event)"
36
+ ></button>
37
+ </td>
38
+ <slot />
39
+ </tr>
40
+ </template>
@@ -1,13 +1,13 @@
1
- <script setup lang="ts">
2
- /** Loading ring (inherits currentColor). With a `label` it is a role=status; without one it is aria-hidden (e.g. inside a button). Classes: .oc-spinner(--sm/--lg/--xl/--primary/--muted) */
3
- defineProps<{ size?: 'sm' | 'md' | 'lg' | 'xl'; color?: 'primary' | 'muted'; label?: string }>()
4
- </script>
5
-
6
- <template>
7
- <span
8
- :class="['oc-spinner', size && size !== 'md' && `oc-spinner--${size}`, color && `oc-spinner--${color}`]"
9
- :role="label ? 'status' : undefined"
10
- :aria-label="label"
11
- :aria-hidden="label ? undefined : 'true'"
12
- ></span>
13
- </template>
1
+ <script setup lang="ts">
2
+ /** Loading ring (inherits currentColor). With a `label` it is a role=status; without one it is aria-hidden (e.g. inside a button). Classes: .oc-spinner(--sm/--lg/--xl/--primary/--muted) */
3
+ defineProps<{ size?: 'sm' | 'md' | 'lg' | 'xl'; color?: 'primary' | 'muted'; label?: string }>()
4
+ </script>
5
+
6
+ <template>
7
+ <span
8
+ :class="['oc-spinner', size && size !== 'md' && `oc-spinner--${size}`, color && `oc-spinner--${color}`]"
9
+ :role="label ? 'status' : undefined"
10
+ :aria-label="label"
11
+ :aria-hidden="label ? undefined : 'true'"
12
+ ></span>
13
+ </template>
@@ -1,24 +1,24 @@
1
- <!-- File: packages/vue/src/components/OcStackCard.vue | Map: props -> article -> deck (OcMediaThumb cover + count) -> title link + meta -->
2
- <script setup lang="ts">
3
- /**
4
- * Stacked deck card for playlists / courses (same markup as snippets/stack-card.html).
5
- * Props: title, href (link covers the card), meta, count ("12 videos"), panel (side panel count), thumb (props for OcMediaThumb).
6
- * Slots: count (replaces the count text), meta. Classes: .oc-stack-card(--panel), __deck, __count, __title, __meta
7
- */
8
- import OcMediaThumb from './OcMediaThumb.vue'
9
-
10
- defineProps<{ title: string; href: string; meta?: string; count?: string; panel?: boolean; thumb?: Record<string, unknown> }>()
11
- </script>
12
-
13
- <template>
14
- <article :class="['oc-stack-card', panel && 'oc-stack-card--panel']">
15
- <div class="oc-stack-card__deck">
16
- <OcMediaThumb v-bind="thumb" />
17
- <span v-if="count || $slots.count" class="oc-stack-card__count"><slot name="count">{{ count }}</slot></span>
18
- </div>
19
- <div>
20
- <h3 class="oc-stack-card__title"><a :href="href">{{ title }}</a></h3>
21
- <p v-if="meta || $slots.meta" class="oc-stack-card__meta"><slot name="meta">{{ meta }}</slot></p>
22
- </div>
23
- </article>
24
- </template>
1
+ <!-- File: packages/vue/src/components/OcStackCard.vue | Map: props -> article -> deck (OcMediaThumb cover + count) -> title link + meta -->
2
+ <script setup lang="ts">
3
+ /**
4
+ * Stacked deck card for playlists / courses (same markup as snippets/stack-card.html).
5
+ * Props: title, href (link covers the card), meta, count ("12 videos"), panel (side panel count), thumb (props for OcMediaThumb).
6
+ * Slots: count (replaces the count text), meta. Classes: .oc-stack-card(--panel), __deck, __count, __title, __meta
7
+ */
8
+ import OcMediaThumb from './OcMediaThumb.vue'
9
+
10
+ defineProps<{ title: string; href: string; meta?: string; count?: string; panel?: boolean; thumb?: Record<string, unknown> }>()
11
+ </script>
12
+
13
+ <template>
14
+ <article :class="['oc-stack-card', panel && 'oc-stack-card--panel']">
15
+ <div class="oc-stack-card__deck">
16
+ <OcMediaThumb v-bind="thumb" />
17
+ <span v-if="count || $slots.count" class="oc-stack-card__count"><slot name="count">{{ count }}</slot></span>
18
+ </div>
19
+ <div>
20
+ <h3 class="oc-stack-card__title"><a :href="href">{{ title }}</a></h3>
21
+ <p v-if="meta || $slots.meta" class="oc-stack-card__meta"><slot name="meta">{{ meta }}</slot></p>
22
+ </div>
23
+ </article>
24
+ </template>
@@ -1,31 +1,31 @@
1
- <!-- File: packages/vue/src/components/OcStackList.vue | Map: props (items, neutral, size) -> ul.oc-stack-list -> li pills -->
2
- <script setup lang="ts">
3
- /**
4
- * Technology pills. Pass `items` (strings or { label, icon }), or your own li.oc-stack-list__item in the default slot.
5
- * Classes: .oc-stack-list (--neutral, --sm), __item, __icon. Accent: class="oc-accent--violet".
6
- */
7
- export interface StackListItem {
8
- label: string
9
- icon?: string
10
- }
11
- withDefaults(
12
- defineProps<{
13
- items?: Array<string | StackListItem>
14
- neutral?: boolean
15
- size?: 'default' | 'sm'
16
- }>(),
17
- { items: () => [], size: 'default' },
18
- )
19
- const label = (item: string | StackListItem) => (typeof item === 'string' ? item : item.label)
20
- const icon = (item: string | StackListItem) => (typeof item === 'string' ? undefined : item.icon)
21
- </script>
22
-
23
- <template>
24
- <ul :class="['oc-stack-list', neutral && 'oc-stack-list--neutral', size === 'sm' && 'oc-stack-list--sm']">
25
- <slot>
26
- <li v-for="(item, i) in items" :key="i" class="oc-stack-list__item">
27
- <span v-if="icon(item)" class="oc-stack-list__icon" aria-hidden="true">{{ icon(item) }}</span>{{ label(item) }}
28
- </li>
29
- </slot>
30
- </ul>
31
- </template>
1
+ <!-- File: packages/vue/src/components/OcStackList.vue | Map: props (items, neutral, size) -> ul.oc-stack-list -> li pills -->
2
+ <script setup lang="ts">
3
+ /**
4
+ * Technology pills. Pass `items` (strings or { label, icon }), or your own li.oc-stack-list__item in the default slot.
5
+ * Classes: .oc-stack-list (--neutral, --sm), __item, __icon. Accent: class="oc-accent--violet".
6
+ */
7
+ export interface StackListItem {
8
+ label: string
9
+ icon?: string
10
+ }
11
+ withDefaults(
12
+ defineProps<{
13
+ items?: Array<string | StackListItem>
14
+ neutral?: boolean
15
+ size?: 'default' | 'sm'
16
+ }>(),
17
+ { items: () => [], size: 'default' },
18
+ )
19
+ const label = (item: string | StackListItem) => (typeof item === 'string' ? item : item.label)
20
+ const icon = (item: string | StackListItem) => (typeof item === 'string' ? undefined : item.icon)
21
+ </script>
22
+
23
+ <template>
24
+ <ul :class="['oc-stack-list', neutral && 'oc-stack-list--neutral', size === 'sm' && 'oc-stack-list--sm']">
25
+ <slot>
26
+ <li v-for="(item, i) in items" :key="i" class="oc-stack-list__item">
27
+ <span v-if="icon(item)" class="oc-stack-list__icon" aria-hidden="true">{{ icon(item) }}</span>{{ label(item) }}
28
+ </li>
29
+ </slot>
30
+ </ul>
31
+ </template>
@@ -1,39 +1,39 @@
1
- <!-- File: packages/vue/src/components/OcStatCard.vue | Map: card (div / a / button) -> icon slot -> body (value + trend, label) -->
2
- <script setup lang="ts">
3
- /**
4
- * Compact KPI tile. With `href` it is a link, with `button` a button (listen to @click), otherwise a div.
5
- * Put several in a <div class="oc-stat-card-grid">. Slots: icon.
6
- * Classes: .oc-stat-card(--accent/--success/--warning/--stripe), -icon, -body, -value, -label, -trend(--up/--down)
7
- */
8
- import { computed } from 'vue'
9
-
10
- const props = withDefaults(
11
- defineProps<{
12
- value: string | number
13
- label: string
14
- trend?: string
15
- trendDirection?: 'up' | 'down'
16
- tone?: 'default' | 'accent' | 'success' | 'warning'
17
- stripe?: boolean
18
- href?: string
19
- button?: boolean
20
- }>(),
21
- { trendDirection: 'up', tone: 'default' },
22
- )
23
- const tag = computed(() => (props.href ? 'a' : props.button ? 'button' : 'div'))
24
- </script>
25
-
26
- <template>
27
- <component
28
- :is="tag"
29
- :class="['oc-stat-card', tone !== 'default' && `oc-stat-card--${tone}`, stripe && 'oc-stat-card--stripe']"
30
- :href="href"
31
- :type="button && !href ? 'button' : undefined"
32
- >
33
- <span v-if="$slots.icon" class="oc-stat-card-icon" aria-hidden="true"><slot name="icon" /></span>
34
- <span class="oc-stat-card-body">
35
- <span class="oc-stat-card-value">{{ value }}<span v-if="trend" :class="['oc-stat-card-trend', `oc-stat-card-trend--${trendDirection}`]">{{ trend }}</span></span>
36
- <span class="oc-stat-card-label">{{ label }}</span>
37
- </span>
38
- </component>
39
- </template>
1
+ <!-- File: packages/vue/src/components/OcStatCard.vue | Map: card (div / a / button) -> icon slot -> body (value + trend, label) -->
2
+ <script setup lang="ts">
3
+ /**
4
+ * Compact KPI tile. With `href` it is a link, with `button` a button (listen to @click), otherwise a div.
5
+ * Put several in a <div class="oc-stat-card-grid">. Slots: icon.
6
+ * Classes: .oc-stat-card(--accent/--success/--warning/--stripe), -icon, -body, -value, -label, -trend(--up/--down)
7
+ */
8
+ import { computed } from 'vue'
9
+
10
+ const props = withDefaults(
11
+ defineProps<{
12
+ value: string | number
13
+ label: string
14
+ trend?: string
15
+ trendDirection?: 'up' | 'down'
16
+ tone?: 'default' | 'accent' | 'success' | 'warning'
17
+ stripe?: boolean
18
+ href?: string
19
+ button?: boolean
20
+ }>(),
21
+ { trendDirection: 'up', tone: 'default' },
22
+ )
23
+ const tag = computed(() => (props.href ? 'a' : props.button ? 'button' : 'div'))
24
+ </script>
25
+
26
+ <template>
27
+ <component
28
+ :is="tag"
29
+ :class="['oc-stat-card', tone !== 'default' && `oc-stat-card--${tone}`, stripe && 'oc-stat-card--stripe']"
30
+ :href="href"
31
+ :type="button && !href ? 'button' : undefined"
32
+ >
33
+ <span v-if="$slots.icon" class="oc-stat-card-icon" aria-hidden="true"><slot name="icon" /></span>
34
+ <span class="oc-stat-card-body">
35
+ <span class="oc-stat-card-value">{{ value }}<span v-if="trend" :class="['oc-stat-card-trend', `oc-stat-card-trend--${trendDirection}`]">{{ trend }}</span></span>
36
+ <span class="oc-stat-card-label">{{ label }}</span>
37
+ </span>
38
+ </component>
39
+ </template>
@@ -1,34 +1,34 @@
1
- <script setup lang="ts">
2
- /**
3
- * Wizard step navigation. v-model = index of the active step (0-based); earlier steps are done and
4
- * clickable, later steps are disabled. Classes: .oc-stepper(--horizontal), .oc-stepper-item(--done/--active),
5
- * -label, -meta.
6
- */
7
- export interface StepperStep {
8
- label: string
9
- /** Small text under the label, e.g. 2/4 */
10
- meta?: string
11
- }
12
- defineProps<{ steps: StepperStep[]; horizontal?: boolean; label?: string }>()
13
- const current = defineModel<number>({ default: 0 })
14
- </script>
15
-
16
- <template>
17
- <ol :class="['oc-stepper', horizontal && 'oc-stepper--horizontal']" :aria-label="label">
18
- <li v-for="(step, i) in steps" :key="i">
19
- <button
20
- :class="['oc-stepper-item', i < current && 'oc-stepper-item--done', i === current && 'oc-stepper-item--active']"
21
- type="button"
22
- :aria-current="i === current ? 'step' : undefined"
23
- :disabled="i > current"
24
- @click="current = i"
25
- >
26
- <span v-if="step.meta">
27
- <span class="oc-stepper-label">{{ step.label }}</span>
28
- <span class="oc-stepper-meta">{{ step.meta }}</span>
29
- </span>
30
- <span v-else class="oc-stepper-label">{{ step.label }}</span>
31
- </button>
32
- </li>
33
- </ol>
34
- </template>
1
+ <script setup lang="ts">
2
+ /**
3
+ * Wizard step navigation. v-model = index of the active step (0-based); earlier steps are done and
4
+ * clickable, later steps are disabled. Classes: .oc-stepper(--horizontal), .oc-stepper-item(--done/--active),
5
+ * -label, -meta.
6
+ */
7
+ export interface StepperStep {
8
+ label: string
9
+ /** Small text under the label, e.g. 2/4 */
10
+ meta?: string
11
+ }
12
+ defineProps<{ steps: StepperStep[]; horizontal?: boolean; label?: string }>()
13
+ const current = defineModel<number>({ default: 0 })
14
+ </script>
15
+
16
+ <template>
17
+ <ol :class="['oc-stepper', horizontal && 'oc-stepper--horizontal']" :aria-label="label">
18
+ <li v-for="(step, i) in steps" :key="i">
19
+ <button
20
+ :class="['oc-stepper-item', i < current && 'oc-stepper-item--done', i === current && 'oc-stepper-item--active']"
21
+ type="button"
22
+ :aria-current="i === current ? 'step' : undefined"
23
+ :disabled="i > current"
24
+ @click="current = i"
25
+ >
26
+ <span v-if="step.meta">
27
+ <span class="oc-stepper-label">{{ step.label }}</span>
28
+ <span class="oc-stepper-meta">{{ step.meta }}</span>
29
+ </span>
30
+ <span v-else class="oc-stepper-label">{{ step.label }}</span>
31
+ </button>
32
+ </li>
33
+ </ol>
34
+ </template>
@@ -1,15 +1,15 @@
1
- <script setup lang="ts">
2
- /** Toggle switch on a checkbox (role="switch"). v-model: boolean. Extra attributes go to the input. */
3
- import { useAttrsSplit } from '../composables/useAttrsSplit'
4
-
5
- defineOptions({ inheritAttrs: false })
6
- const model = defineModel<boolean>({ default: false })
7
- const { root, control } = useAttrsSplit()
8
- </script>
9
-
10
- <template>
11
- <label v-bind="root" class="oc-switch">
12
- <input v-bind="control" v-model="model" type="checkbox" role="switch" />
13
- <span class="oc-switch-track"></span>
14
- </label>
15
- </template>
1
+ <script setup lang="ts">
2
+ /** Toggle switch on a checkbox (role="switch"). v-model: boolean. Extra attributes go to the input. */
3
+ import { useAttrsSplit } from '../composables/useAttrsSplit'
4
+
5
+ defineOptions({ inheritAttrs: false })
6
+ const model = defineModel<boolean>({ default: false })
7
+ const { root, control } = useAttrsSplit()
8
+ </script>
9
+
10
+ <template>
11
+ <label v-bind="root" class="oc-switch">
12
+ <input v-bind="control" v-model="model" type="checkbox" role="switch" />
13
+ <span class="oc-switch-track"></span>
14
+ </label>
15
+ </template>