@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.
- package/LICENSE +21 -21
- package/README.md +49 -49
- package/dist/omniaui-vue.js.map +1 -1
- package/package.json +69 -69
- package/src/blocks/OcBlockAboutTimeline.vue +44 -44
- package/src/blocks/OcBlockAppHeader.vue +36 -36
- package/src/blocks/OcBlockAppShell.vue +29 -29
- package/src/blocks/OcBlockAuth.vue +24 -24
- package/src/blocks/OcBlockAuthSplit.vue +47 -47
- package/src/blocks/OcBlockContactGrid.vue +53 -53
- package/src/blocks/OcBlockCta.vue +12 -12
- package/src/blocks/OcBlockDataTable.vue +27 -27
- package/src/blocks/OcBlockFaq.vue +49 -49
- package/src/blocks/OcBlockFeatures.vue +23 -23
- package/src/blocks/OcBlockFooter.vue +25 -25
- package/src/blocks/OcBlockFormPage.vue +24 -24
- package/src/blocks/OcBlockHero.vue +13 -13
- package/src/blocks/OcBlockHeroCode.vue +42 -42
- package/src/blocks/OcBlockHeroOrbit.vue +69 -69
- package/src/blocks/OcBlockHeroSplit.vue +15 -15
- package/src/blocks/OcBlockModuleHeader.vue +21 -21
- package/src/blocks/OcBlockPageHero.vue +13 -13
- package/src/blocks/OcBlockPortfolioGrid.vue +63 -63
- package/src/blocks/OcBlockPricing.vue +39 -39
- package/src/blocks/OcBlockProcess.vue +39 -39
- package/src/blocks/OcBlockProductGrid.vue +41 -41
- package/src/blocks/OcBlockProfileHeader.vue +50 -50
- package/src/blocks/OcBlockShowcase.vue +43 -43
- package/src/blocks/OcBlockSiteFooter.vue +54 -54
- package/src/blocks/OcBlockSiteHeader.vue +34 -34
- package/src/blocks/OcBlockSpotlight.vue +47 -47
- package/src/blocks/OcBlockStats.vue +17 -17
- package/src/blocks/OcBlockStatsCounter.vue +20 -20
- package/src/blocks/OcBlockTeamList.vue +53 -53
- package/src/blocks/OcBlockTwoFactor.vue +61 -61
- package/src/blocks/OcBlockWizardDialog.vue +67 -67
- package/src/components/OcAccordion.vue +12 -12
- package/src/components/OcAccordionAccent.vue +27 -27
- package/src/components/OcAccordionItem.vue +19 -19
- package/src/components/OcAffixInput.vue +40 -40
- package/src/components/OcAlert.vue +17 -17
- package/src/components/OcAlertDialog.vue +66 -66
- package/src/components/OcAlphaTabs.vue +54 -54
- package/src/components/OcAspectRatio.vue +21 -21
- package/src/components/OcAttachment.vue +59 -59
- package/src/components/OcAttachmentImage.vue +13 -13
- package/src/components/OcAttachmentList.vue +31 -31
- package/src/components/OcAttachmentThumb.vue +14 -14
- package/src/components/OcAvatar.vue +18 -18
- package/src/components/OcAvatarGroup.vue +7 -7
- package/src/components/OcBackLink.vue +8 -8
- package/src/components/OcBadge.vue +13 -13
- package/src/components/OcBarcodeInput.vue +51 -51
- package/src/components/OcBreadcrumb.vue +22 -22
- package/src/components/OcBrowserFrame.vue +33 -33
- package/src/components/OcBusyOverlay.vue +32 -32
- package/src/components/OcButton.vue +47 -47
- package/src/components/OcButtonGroup.vue +10 -10
- package/src/components/OcButtonGroupText.vue +7 -7
- package/src/components/OcCard.vue +20 -20
- package/src/components/OcChartLine.vue +80 -80
- package/src/components/OcChatComposer.vue +42 -42
- package/src/components/OcCheckbox.vue +26 -26
- package/src/components/OcChecklist.vue +29 -29
- package/src/components/OcCollapsible.vue +19 -19
- package/src/components/OcColorField.vue +15 -15
- package/src/components/OcColorSelect.vue +33 -33
- package/src/components/OcColumnMenu.vue +50 -50
- package/src/components/OcCommand.vue +119 -119
- package/src/components/OcConfirmDialog.vue +65 -65
- package/src/components/OcCookieConsent.vue +119 -119
- package/src/components/OcCopyField.vue +37 -37
- package/src/components/OcCounter.vue +15 -15
- package/src/components/OcDataTable.vue +144 -144
- package/src/components/OcDefinitionList.vue +35 -35
- package/src/components/OcDropdown.vue +23 -23
- package/src/components/OcDropdownItem.vue +9 -9
- package/src/components/OcDropdownLabel.vue +7 -7
- package/src/components/OcDropdownSeparator.vue +7 -7
- package/src/components/OcDropzone.vue +36 -36
- package/src/components/OcEmojiPicker.vue +45 -45
- package/src/components/OcEmptyState.vue +13 -13
- package/src/components/OcEntityCard.vue +47 -47
- package/src/components/OcFactList.vue +37 -37
- package/src/components/OcFilterCounts.vue +38 -38
- package/src/components/OcFlipCard.vue +36 -36
- package/src/components/OcFormField.vue +36 -36
- package/src/components/OcGreeting.vue +52 -52
- package/src/components/OcHeading.vue +19 -19
- package/src/components/OcHoverCard.vue +25 -25
- package/src/components/OcImageZoom.vue +39 -39
- package/src/components/OcInput.vue +9 -9
- package/src/components/OcInputGroup.vue +12 -12
- package/src/components/OcItem.vue +40 -40
- package/src/components/OcItemGroup.vue +7 -7
- package/src/components/OcItemSeparator.vue +7 -7
- package/src/components/OcKbd.vue +7 -7
- package/src/components/OcKbdGroup.vue +15 -15
- package/src/components/OcLabel.vue +10 -10
- package/src/components/OcLanguageSelect.vue +40 -40
- package/src/components/OcLauncherCard.vue +34 -34
- package/src/components/OcLightbox.vue +63 -63
- package/src/components/OcLinkArrow.vue +25 -25
- package/src/components/OcListToolbar.vue +44 -44
- package/src/components/OcMarquee.vue +36 -36
- package/src/components/OcMediaCard.vue +28 -28
- package/src/components/OcMediaRow.vue +28 -28
- package/src/components/OcMediaThumb.vue +38 -38
- package/src/components/OcMessage.vue +91 -91
- package/src/components/OcMessageList.vue +43 -43
- package/src/components/OcMessageThread.vue +155 -155
- package/src/components/OcModal.vue +42 -42
- package/src/components/OcNavmenu.vue +18 -18
- package/src/components/OcNavmenuList.vue +38 -38
- package/src/components/OcNextTeaser.vue +25 -25
- package/src/components/OcNumberInput.vue +47 -47
- package/src/components/OcOtpInput.vue +34 -34
- package/src/components/OcPageHeader.vue +34 -34
- package/src/components/OcPagination.vue +33 -33
- package/src/components/OcPasswordInput.vue +27 -27
- package/src/components/OcPasswordRequirements.vue +28 -28
- package/src/components/OcPhoneInput.vue +72 -72
- package/src/components/OcPopover.vue +25 -25
- package/src/components/OcPriceCard.vue +69 -69
- package/src/components/OcProductMark.vue +31 -31
- package/src/components/OcProgress.vue +21 -21
- package/src/components/OcProjectCard.vue +36 -36
- package/src/components/OcProse.vue +57 -57
- package/src/components/OcRadio.vue +40 -40
- package/src/components/OcRadioGroup.vue +32 -32
- package/src/components/OcRecoveryCodes.vue +55 -55
- package/src/components/OcScrollArea.vue +15 -15
- package/src/components/OcSegmented.vue +28 -28
- package/src/components/OcSelect.vue +21 -21
- package/src/components/OcSeparator.vue +18 -18
- package/src/components/OcSeverityCard.vue +46 -46
- package/src/components/OcSheet.vue +49 -49
- package/src/components/OcSidebarCollapsible.vue +19 -19
- package/src/components/OcSidebarGroup.vue +11 -11
- package/src/components/OcSidebarMenu.vue +7 -7
- package/src/components/OcSidebarMenuButton.vue +31 -31
- package/src/components/OcSidebarSeparator.vue +7 -7
- package/src/components/OcSkeleton.vue +8 -8
- package/src/components/OcSlider.vue +27 -27
- package/src/components/OcSortableRow.vue +40 -40
- package/src/components/OcSpinner.vue +13 -13
- package/src/components/OcStackCard.vue +24 -24
- package/src/components/OcStackList.vue +31 -31
- package/src/components/OcStatCard.vue +39 -39
- package/src/components/OcStepper.vue +34 -34
- package/src/components/OcSwitch.vue +15 -15
- package/src/components/OcTable.vue +115 -115
- package/src/components/OcTableActions.vue +26 -26
- package/src/components/OcTableCompact.vue +46 -46
- package/src/components/OcTabs.vue +37 -37
- package/src/components/OcTagInput.vue +50 -50
- package/src/components/OcTerminalLog.vue +50 -50
- package/src/components/OcTextarea.vue +9 -9
- package/src/components/OcThemeSwitch.vue +31 -31
- package/src/components/OcTimeInput.vue +50 -50
- package/src/components/OcTimeline.vue +36 -36
- package/src/components/OcToast.vue +31 -31
- package/src/components/OcToastContainer.vue +21 -21
- package/src/components/OcToggle.vue +63 -63
- package/src/components/OcToggleField.vue +28 -28
- package/src/components/OcToggleGroup.vue +40 -40
- package/src/components/OcTooltip.vue +8 -8
- package/src/components/OcTopProgress.vue +54 -54
- package/src/components/OcTree.vue +70 -70
- package/src/components/OcUpgradeBanner.vue +42 -42
- package/src/components/OcUser.vue +25 -25
- package/src/components/OcVersionBanner.vue +34 -34
- package/src/composables/chartLine.ts +28 -28
- package/src/composables/keys.ts +22 -22
- package/src/composables/useAttrsSplit.ts +16 -16
- package/src/composables/useDialog.ts +21 -21
- package/src/composables/useToast.ts +66 -66
- 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>
|