@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.
- 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,54 +1,54 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
* Brand column, link columns, a contact column and a bottom bar.
|
|
4
|
-
* Slots: brand (the logo link), about (default: `about` text), bottom-start, bottom-end.
|
|
5
|
-
* Classes: .oc-site-footer, __grid, __about, __title, __list, __bottom, .oc-site-header__brand
|
|
6
|
-
*/
|
|
7
|
-
export interface SiteFooterColumn {
|
|
8
|
-
title: string
|
|
9
|
-
links: { label: string; href: string }[]
|
|
10
|
-
}
|
|
11
|
-
export interface SiteFooterContact {
|
|
12
|
-
title: string
|
|
13
|
-
lines: { label: string; href?: string }[]
|
|
14
|
-
}
|
|
15
|
-
defineProps<{
|
|
16
|
-
about?: string
|
|
17
|
-
columns?: SiteFooterColumn[]
|
|
18
|
-
contact?: SiteFooterContact
|
|
19
|
-
copyright?: string
|
|
20
|
-
credit?: string
|
|
21
|
-
}>()
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<template>
|
|
25
|
-
<footer class="oc-site-footer">
|
|
26
|
-
<div class="oc-container">
|
|
27
|
-
<div class="oc-site-footer__grid">
|
|
28
|
-
<div class="oc-site-footer__about">
|
|
29
|
-
<slot name="brand" />
|
|
30
|
-
<p v-if="about">{{ about }}</p>
|
|
31
|
-
</div>
|
|
32
|
-
<div v-for="col in columns" :key="col.title">
|
|
33
|
-
<h2 class="oc-site-footer__title">{{ col.title }}</h2>
|
|
34
|
-
<ul class="oc-site-footer__list">
|
|
35
|
-
<li v-for="link in col.links" :key="link.href + link.label"><a :href="link.href">{{ link.label }}</a></li>
|
|
36
|
-
</ul>
|
|
37
|
-
</div>
|
|
38
|
-
<div v-if="contact">
|
|
39
|
-
<h2 class="oc-site-footer__title">{{ contact.title }}</h2>
|
|
40
|
-
<address class="oc-site-footer__list">
|
|
41
|
-
<template v-for="line in contact.lines" :key="line.label">
|
|
42
|
-
<a v-if="line.href" :href="line.href">{{ line.label }}</a>
|
|
43
|
-
<span v-else>{{ line.label }}</span>
|
|
44
|
-
</template>
|
|
45
|
-
</address>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
<div v-if="copyright || credit || $slots['bottom-start'] || $slots['bottom-end']" class="oc-site-footer__bottom">
|
|
49
|
-
<span><slot name="bottom-start">{{ copyright }}</slot></span>
|
|
50
|
-
<span><slot name="bottom-end">{{ credit }}</slot></span>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
</footer>
|
|
54
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Brand column, link columns, a contact column and a bottom bar.
|
|
4
|
+
* Slots: brand (the logo link), about (default: `about` text), bottom-start, bottom-end.
|
|
5
|
+
* Classes: .oc-site-footer, __grid, __about, __title, __list, __bottom, .oc-site-header__brand
|
|
6
|
+
*/
|
|
7
|
+
export interface SiteFooterColumn {
|
|
8
|
+
title: string
|
|
9
|
+
links: { label: string; href: string }[]
|
|
10
|
+
}
|
|
11
|
+
export interface SiteFooterContact {
|
|
12
|
+
title: string
|
|
13
|
+
lines: { label: string; href?: string }[]
|
|
14
|
+
}
|
|
15
|
+
defineProps<{
|
|
16
|
+
about?: string
|
|
17
|
+
columns?: SiteFooterColumn[]
|
|
18
|
+
contact?: SiteFooterContact
|
|
19
|
+
copyright?: string
|
|
20
|
+
credit?: string
|
|
21
|
+
}>()
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<footer class="oc-site-footer">
|
|
26
|
+
<div class="oc-container">
|
|
27
|
+
<div class="oc-site-footer__grid">
|
|
28
|
+
<div class="oc-site-footer__about">
|
|
29
|
+
<slot name="brand" />
|
|
30
|
+
<p v-if="about">{{ about }}</p>
|
|
31
|
+
</div>
|
|
32
|
+
<div v-for="col in columns" :key="col.title">
|
|
33
|
+
<h2 class="oc-site-footer__title">{{ col.title }}</h2>
|
|
34
|
+
<ul class="oc-site-footer__list">
|
|
35
|
+
<li v-for="link in col.links" :key="link.href + link.label"><a :href="link.href">{{ link.label }}</a></li>
|
|
36
|
+
</ul>
|
|
37
|
+
</div>
|
|
38
|
+
<div v-if="contact">
|
|
39
|
+
<h2 class="oc-site-footer__title">{{ contact.title }}</h2>
|
|
40
|
+
<address class="oc-site-footer__list">
|
|
41
|
+
<template v-for="line in contact.lines" :key="line.label">
|
|
42
|
+
<a v-if="line.href" :href="line.href">{{ line.label }}</a>
|
|
43
|
+
<span v-else>{{ line.label }}</span>
|
|
44
|
+
</template>
|
|
45
|
+
</address>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div v-if="copyright || credit || $slots['bottom-start'] || $slots['bottom-end']" class="oc-site-footer__bottom">
|
|
49
|
+
<span><slot name="bottom-start">{{ copyright }}</slot></span>
|
|
50
|
+
<span><slot name="bottom-end">{{ credit }}</slot></span>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</footer>
|
|
54
|
+
</template>
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
* Sticky header that turns into glass after scrolling; the mobile menu is a popover. No JavaScript needed.
|
|
4
|
-
* Slots: brand (inside the brand link), nav (replaces the items), cta (the trailing button).
|
|
5
|
-
* Classes: .oc-site-header, __inner, __brand, __toggle, __nav, .oc-container
|
|
6
|
-
*/
|
|
7
|
-
import { useUid } from '../composables/useUid'
|
|
8
|
-
|
|
9
|
-
export interface SiteHeaderLink {
|
|
10
|
-
label: string
|
|
11
|
-
href: string
|
|
12
|
-
current?: boolean
|
|
13
|
-
}
|
|
14
|
-
withDefaults(
|
|
15
|
-
defineProps<{ items?: SiteHeaderLink[]; homeHref?: string; menuLabel?: string; navLabel?: string }>(),
|
|
16
|
-
{ items: () => [], homeHref: '/', menuLabel: 'Menu', navLabel: 'Main' },
|
|
17
|
-
)
|
|
18
|
-
const navId = useUid('oc-site-nav')
|
|
19
|
-
</script>
|
|
20
|
-
|
|
21
|
-
<template>
|
|
22
|
-
<header class="oc-site-header">
|
|
23
|
-
<div class="oc-container oc-site-header__inner">
|
|
24
|
-
<a class="oc-site-header__brand" :href="homeHref"><slot name="brand" /></a>
|
|
25
|
-
<button class="oc-site-header__toggle" type="button" :popovertarget="navId" :aria-label="menuLabel">☰</button>
|
|
26
|
-
<nav :id="navId" class="oc-site-header__nav" popover :aria-label="navLabel">
|
|
27
|
-
<slot name="nav">
|
|
28
|
-
<a v-for="item in items" :key="item.href + item.label" :href="item.href" :aria-current="item.current ? 'page' : undefined">{{ item.label }}</a>
|
|
29
|
-
</slot>
|
|
30
|
-
<slot name="cta" />
|
|
31
|
-
</nav>
|
|
32
|
-
</div>
|
|
33
|
-
</header>
|
|
34
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Sticky header that turns into glass after scrolling; the mobile menu is a popover. No JavaScript needed.
|
|
4
|
+
* Slots: brand (inside the brand link), nav (replaces the items), cta (the trailing button).
|
|
5
|
+
* Classes: .oc-site-header, __inner, __brand, __toggle, __nav, .oc-container
|
|
6
|
+
*/
|
|
7
|
+
import { useUid } from '../composables/useUid'
|
|
8
|
+
|
|
9
|
+
export interface SiteHeaderLink {
|
|
10
|
+
label: string
|
|
11
|
+
href: string
|
|
12
|
+
current?: boolean
|
|
13
|
+
}
|
|
14
|
+
withDefaults(
|
|
15
|
+
defineProps<{ items?: SiteHeaderLink[]; homeHref?: string; menuLabel?: string; navLabel?: string }>(),
|
|
16
|
+
{ items: () => [], homeHref: '/', menuLabel: 'Menu', navLabel: 'Main' },
|
|
17
|
+
)
|
|
18
|
+
const navId = useUid('oc-site-nav')
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<header class="oc-site-header">
|
|
23
|
+
<div class="oc-container oc-site-header__inner">
|
|
24
|
+
<a class="oc-site-header__brand" :href="homeHref"><slot name="brand" /></a>
|
|
25
|
+
<button class="oc-site-header__toggle" type="button" :popovertarget="navId" :aria-label="menuLabel">☰</button>
|
|
26
|
+
<nav :id="navId" class="oc-site-header__nav" popover :aria-label="navLabel">
|
|
27
|
+
<slot name="nav">
|
|
28
|
+
<a v-for="item in items" :key="item.href + item.label" :href="item.href" :aria-current="item.current ? 'page' : undefined">{{ item.label }}</a>
|
|
29
|
+
</slot>
|
|
30
|
+
<slot name="cta" />
|
|
31
|
+
</nav>
|
|
32
|
+
</div>
|
|
33
|
+
</header>
|
|
34
|
+
</template>
|
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
* Highlighted flagship product: badge, big title with icon tile, tagline, copy, button and a module list.
|
|
4
|
-
* Slots: cta (default: a gradient link from `ctaLabel` / `ctaHref`). Classes: .oc-spotlight(__title/__tagline/__modules),
|
|
5
|
-
* .oc-accent--<name>, .oc-pill--accent, .oc-status-dot, .oc-icon-tile(--lg/--sm), .oc-lead
|
|
6
|
-
*/
|
|
7
|
-
export interface SpotlightModule {
|
|
8
|
-
icon?: string
|
|
9
|
-
label: string
|
|
10
|
-
}
|
|
11
|
-
defineProps<{
|
|
12
|
-
accent?: string
|
|
13
|
-
badge?: string
|
|
14
|
-
icon?: string
|
|
15
|
-
title: string
|
|
16
|
-
tagline?: string
|
|
17
|
-
lead?: string
|
|
18
|
-
ctaLabel?: string
|
|
19
|
-
ctaHref?: string
|
|
20
|
-
modules?: SpotlightModule[]
|
|
21
|
-
}>()
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<template>
|
|
25
|
-
<section class="oc-section-pad">
|
|
26
|
-
<div class="oc-container">
|
|
27
|
-
<div :class="['oc-spotlight', accent && `oc-accent--${accent}`]">
|
|
28
|
-
<div>
|
|
29
|
-
<span v-if="badge" class="oc-pill oc-pill--accent"><span class="oc-status-dot"></span>{{ badge }}</span>
|
|
30
|
-
<h2 class="oc-spotlight__title">
|
|
31
|
-
<span v-if="icon" class="oc-icon-tile oc-icon-tile--lg" aria-hidden="true">{{ icon }}</span>{{ title }}
|
|
32
|
-
</h2>
|
|
33
|
-
<p v-if="tagline" class="oc-spotlight__tagline">{{ tagline }}</p>
|
|
34
|
-
<p v-if="lead" class="oc-lead">{{ lead }}</p>
|
|
35
|
-
<slot name="cta">
|
|
36
|
-
<a v-if="ctaLabel" class="oc-btn oc-btn--gradient oc-btn--lg" :href="ctaHref ?? '#'">{{ ctaLabel }}</a>
|
|
37
|
-
</slot>
|
|
38
|
-
</div>
|
|
39
|
-
<ul v-if="modules?.length" class="oc-spotlight__modules">
|
|
40
|
-
<li v-for="m in modules" :key="m.label">
|
|
41
|
-
<span class="oc-icon-tile oc-icon-tile--sm" aria-hidden="true">{{ m.icon }}</span>{{ m.label }}
|
|
42
|
-
</li>
|
|
43
|
-
</ul>
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
46
|
-
</section>
|
|
47
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Highlighted flagship product: badge, big title with icon tile, tagline, copy, button and a module list.
|
|
4
|
+
* Slots: cta (default: a gradient link from `ctaLabel` / `ctaHref`). Classes: .oc-spotlight(__title/__tagline/__modules),
|
|
5
|
+
* .oc-accent--<name>, .oc-pill--accent, .oc-status-dot, .oc-icon-tile(--lg/--sm), .oc-lead
|
|
6
|
+
*/
|
|
7
|
+
export interface SpotlightModule {
|
|
8
|
+
icon?: string
|
|
9
|
+
label: string
|
|
10
|
+
}
|
|
11
|
+
defineProps<{
|
|
12
|
+
accent?: string
|
|
13
|
+
badge?: string
|
|
14
|
+
icon?: string
|
|
15
|
+
title: string
|
|
16
|
+
tagline?: string
|
|
17
|
+
lead?: string
|
|
18
|
+
ctaLabel?: string
|
|
19
|
+
ctaHref?: string
|
|
20
|
+
modules?: SpotlightModule[]
|
|
21
|
+
}>()
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<section class="oc-section-pad">
|
|
26
|
+
<div class="oc-container">
|
|
27
|
+
<div :class="['oc-spotlight', accent && `oc-accent--${accent}`]">
|
|
28
|
+
<div>
|
|
29
|
+
<span v-if="badge" class="oc-pill oc-pill--accent"><span class="oc-status-dot"></span>{{ badge }}</span>
|
|
30
|
+
<h2 class="oc-spotlight__title">
|
|
31
|
+
<span v-if="icon" class="oc-icon-tile oc-icon-tile--lg" aria-hidden="true">{{ icon }}</span>{{ title }}
|
|
32
|
+
</h2>
|
|
33
|
+
<p v-if="tagline" class="oc-spotlight__tagline">{{ tagline }}</p>
|
|
34
|
+
<p v-if="lead" class="oc-lead">{{ lead }}</p>
|
|
35
|
+
<slot name="cta">
|
|
36
|
+
<a v-if="ctaLabel" class="oc-btn oc-btn--gradient oc-btn--lg" :href="ctaHref ?? '#'">{{ ctaLabel }}</a>
|
|
37
|
+
</slot>
|
|
38
|
+
</div>
|
|
39
|
+
<ul v-if="modules?.length" class="oc-spotlight__modules">
|
|
40
|
+
<li v-for="m in modules" :key="m.label">
|
|
41
|
+
<span class="oc-icon-tile oc-icon-tile--sm" aria-hidden="true">{{ m.icon }}</span>{{ m.label }}
|
|
42
|
+
</li>
|
|
43
|
+
</ul>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</section>
|
|
47
|
+
</template>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/** Key figures row. Classes: .oc-block-stats, -stat, -stat-value, -stat-label */
|
|
3
|
-
export interface StatItem {
|
|
4
|
-
value: string
|
|
5
|
-
label: string
|
|
6
|
-
}
|
|
7
|
-
defineProps<{ items: StatItem[] }>()
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<template>
|
|
11
|
-
<div class="oc-block-stats">
|
|
12
|
-
<div v-for="item in items" :key="item.label" class="oc-block-stat">
|
|
13
|
-
<div class="oc-block-stat-value">{{ item.value }}</div>
|
|
14
|
-
<div class="oc-block-stat-label">{{ item.label }}</div>
|
|
15
|
-
</div>
|
|
16
|
-
</div>
|
|
17
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Key figures row. Classes: .oc-block-stats, -stat, -stat-value, -stat-label */
|
|
3
|
+
export interface StatItem {
|
|
4
|
+
value: string
|
|
5
|
+
label: string
|
|
6
|
+
}
|
|
7
|
+
defineProps<{ items: StatItem[] }>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div class="oc-block-stats">
|
|
12
|
+
<div v-for="item in items" :key="item.label" class="oc-block-stat">
|
|
13
|
+
<div class="oc-block-stat-value">{{ item.value }}</div>
|
|
14
|
+
<div class="oc-block-stat-label">{{ item.label }}</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/** Key figures that count up when they scroll into view (CSS only). Classes: .oc-block-stats, -stat, -stat-value + .oc-counter, -stat-label */
|
|
3
|
-
import OcCounter from '../components/OcCounter.vue'
|
|
4
|
-
|
|
5
|
-
export interface CounterStat {
|
|
6
|
-
to: number
|
|
7
|
-
suffix?: string
|
|
8
|
-
label: string
|
|
9
|
-
}
|
|
10
|
-
defineProps<{ items: CounterStat[] }>()
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<div class="oc-block-stats">
|
|
15
|
-
<div v-for="item in items" :key="item.label" class="oc-block-stat">
|
|
16
|
-
<OcCounter class="oc-block-stat-value" :to="item.to" :suffix="item.suffix" />
|
|
17
|
-
<span class="oc-block-stat-label">{{ item.label }}</span>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Key figures that count up when they scroll into view (CSS only). Classes: .oc-block-stats, -stat, -stat-value + .oc-counter, -stat-label */
|
|
3
|
+
import OcCounter from '../components/OcCounter.vue'
|
|
4
|
+
|
|
5
|
+
export interface CounterStat {
|
|
6
|
+
to: number
|
|
7
|
+
suffix?: string
|
|
8
|
+
label: string
|
|
9
|
+
}
|
|
10
|
+
defineProps<{ items: CounterStat[] }>()
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<div class="oc-block-stats">
|
|
15
|
+
<div v-for="item in items" :key="item.label" class="oc-block-stat">
|
|
16
|
+
<OcCounter class="oc-block-stat-value" :to="item.to" :suffix="item.suffix" />
|
|
17
|
+
<span class="oc-block-stat-label">{{ item.label }}</span>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
* Member rows with avatar, role badge and a row action menu (popover). Emits `action` ({ member, action }).
|
|
4
|
-
* Slot `meta` (scoped: { member }) adds extra badges. Classes: .oc-block-team, -row, -meta, .oc-user, .oc-dropdown-menu
|
|
5
|
-
*/
|
|
6
|
-
import { useUid } from '../composables/useUid'
|
|
7
|
-
|
|
8
|
-
export interface TeamAction {
|
|
9
|
-
label: string
|
|
10
|
-
href?: string
|
|
11
|
-
/** Draw a separator line before this action */
|
|
12
|
-
separator?: boolean
|
|
13
|
-
}
|
|
14
|
-
export interface TeamMember {
|
|
15
|
-
name: string
|
|
16
|
-
email?: string
|
|
17
|
-
initials?: string
|
|
18
|
-
role?: string
|
|
19
|
-
roleVariant?: 'default' | 'secondary' | 'outline' | 'destructive' | 'success' | 'warning' | 'info'
|
|
20
|
-
actions?: TeamAction[]
|
|
21
|
-
}
|
|
22
|
-
defineProps<{ members: TeamMember[]; actionsLabel?: string }>()
|
|
23
|
-
defineEmits<{ action: [payload: { member: TeamMember; action: TeamAction }] }>()
|
|
24
|
-
const base = useUid('oc-team-menu')
|
|
25
|
-
</script>
|
|
26
|
-
|
|
27
|
-
<template>
|
|
28
|
-
<div class="oc-block-team">
|
|
29
|
-
<div v-for="(member, i) in members" :key="member.email ?? member.name" class="oc-block-team-row">
|
|
30
|
-
<div class="oc-user">
|
|
31
|
-
<span class="oc-avatar">{{ member.initials }}</span>
|
|
32
|
-
<span class="oc-user-text">
|
|
33
|
-
<span class="oc-user-name">{{ member.name }}</span>
|
|
34
|
-
<span v-if="member.email" class="oc-user-email">{{ member.email }}</span>
|
|
35
|
-
</span>
|
|
36
|
-
</div>
|
|
37
|
-
<div class="oc-block-team-meta">
|
|
38
|
-
<span v-if="member.role" :class="['oc-badge', member.roleVariant && member.roleVariant !== 'default' && `oc-badge--${member.roleVariant}`]">{{ member.role }}</span>
|
|
39
|
-
<slot name="meta" :member="member" />
|
|
40
|
-
<template v-if="member.actions?.length">
|
|
41
|
-
<button class="oc-btn oc-btn--ghost oc-btn--icon oc-btn--sm" type="button" :popovertarget="`${base}-${i}`" :aria-label="actionsLabel ?? 'Member actions'">…</button>
|
|
42
|
-
<div :id="`${base}-${i}`" class="oc-dropdown-menu" popover>
|
|
43
|
-
<template v-for="action in member.actions" :key="action.label">
|
|
44
|
-
<div v-if="action.separator" class="oc-dropdown-separator"></div>
|
|
45
|
-
<a v-if="action.href" class="oc-dropdown-item" :href="action.href" @click="$emit('action', { member, action })">{{ action.label }}</a>
|
|
46
|
-
<button v-else class="oc-dropdown-item" type="button" @click="$emit('action', { member, action })">{{ action.label }}</button>
|
|
47
|
-
</template>
|
|
48
|
-
</div>
|
|
49
|
-
</template>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Member rows with avatar, role badge and a row action menu (popover). Emits `action` ({ member, action }).
|
|
4
|
+
* Slot `meta` (scoped: { member }) adds extra badges. Classes: .oc-block-team, -row, -meta, .oc-user, .oc-dropdown-menu
|
|
5
|
+
*/
|
|
6
|
+
import { useUid } from '../composables/useUid'
|
|
7
|
+
|
|
8
|
+
export interface TeamAction {
|
|
9
|
+
label: string
|
|
10
|
+
href?: string
|
|
11
|
+
/** Draw a separator line before this action */
|
|
12
|
+
separator?: boolean
|
|
13
|
+
}
|
|
14
|
+
export interface TeamMember {
|
|
15
|
+
name: string
|
|
16
|
+
email?: string
|
|
17
|
+
initials?: string
|
|
18
|
+
role?: string
|
|
19
|
+
roleVariant?: 'default' | 'secondary' | 'outline' | 'destructive' | 'success' | 'warning' | 'info'
|
|
20
|
+
actions?: TeamAction[]
|
|
21
|
+
}
|
|
22
|
+
defineProps<{ members: TeamMember[]; actionsLabel?: string }>()
|
|
23
|
+
defineEmits<{ action: [payload: { member: TeamMember; action: TeamAction }] }>()
|
|
24
|
+
const base = useUid('oc-team-menu')
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<div class="oc-block-team">
|
|
29
|
+
<div v-for="(member, i) in members" :key="member.email ?? member.name" class="oc-block-team-row">
|
|
30
|
+
<div class="oc-user">
|
|
31
|
+
<span class="oc-avatar">{{ member.initials }}</span>
|
|
32
|
+
<span class="oc-user-text">
|
|
33
|
+
<span class="oc-user-name">{{ member.name }}</span>
|
|
34
|
+
<span v-if="member.email" class="oc-user-email">{{ member.email }}</span>
|
|
35
|
+
</span>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="oc-block-team-meta">
|
|
38
|
+
<span v-if="member.role" :class="['oc-badge', member.roleVariant && member.roleVariant !== 'default' && `oc-badge--${member.roleVariant}`]">{{ member.role }}</span>
|
|
39
|
+
<slot name="meta" :member="member" />
|
|
40
|
+
<template v-if="member.actions?.length">
|
|
41
|
+
<button class="oc-btn oc-btn--ghost oc-btn--icon oc-btn--sm" type="button" :popovertarget="`${base}-${i}`" :aria-label="actionsLabel ?? 'Member actions'">…</button>
|
|
42
|
+
<div :id="`${base}-${i}`" class="oc-dropdown-menu" popover>
|
|
43
|
+
<template v-for="action in member.actions" :key="action.label">
|
|
44
|
+
<div v-if="action.separator" class="oc-dropdown-separator"></div>
|
|
45
|
+
<a v-if="action.href" class="oc-dropdown-item" :href="action.href" @click="$emit('action', { member, action })">{{ action.label }}</a>
|
|
46
|
+
<button v-else class="oc-dropdown-item" type="button" @click="$emit('action', { member, action })">{{ action.label }}</button>
|
|
47
|
+
</template>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
* Authenticator setup: QR, copyable key, OTP code and recovery codes. v-model = the typed code.
|
|
4
|
-
* Emits `submit` with the code (form submit of the confirm step). Slot `qr` replaces the QR placeholder.
|
|
5
|
-
* Classes: .oc-block-twofactor, -step, -center, -qr; reuses copy-field, otp, recovery-codes components.
|
|
6
|
-
*/
|
|
7
|
-
import OcCopyField from '../components/OcCopyField.vue'
|
|
8
|
-
import OcOtpInput from '../components/OcOtpInput.vue'
|
|
9
|
-
import OcRecoveryCodes from '../components/OcRecoveryCodes.vue'
|
|
10
|
-
import { useUid } from '../composables/useUid'
|
|
11
|
-
|
|
12
|
-
withDefaults(
|
|
13
|
-
defineProps<{
|
|
14
|
-
setupKey: string
|
|
15
|
-
recoveryCodes?: string[]
|
|
16
|
-
length?: number
|
|
17
|
-
scanTitle?: string
|
|
18
|
-
scanText?: string
|
|
19
|
-
confirmTitle?: string
|
|
20
|
-
codeLabel?: string
|
|
21
|
-
submitLabel?: string
|
|
22
|
-
}>(),
|
|
23
|
-
{
|
|
24
|
-
length: 6,
|
|
25
|
-
scanTitle: '1. Scan the QR code',
|
|
26
|
-
scanText: 'Use an authenticator app, or enter the key manually.',
|
|
27
|
-
confirmTitle: '2. Confirm with a code',
|
|
28
|
-
codeLabel: 'Authentication code',
|
|
29
|
-
submitLabel: 'Enable two-factor',
|
|
30
|
-
},
|
|
31
|
-
)
|
|
32
|
-
defineEmits<{ submit: [code: string] }>()
|
|
33
|
-
const code = defineModel<string>({ default: '' })
|
|
34
|
-
const codeId = useUid('oc-twofactor-code')
|
|
35
|
-
</script>
|
|
36
|
-
|
|
37
|
-
<template>
|
|
38
|
-
<div class="oc-block-twofactor">
|
|
39
|
-
<section class="oc-block-twofactor-step">
|
|
40
|
-
<div class="oc-heading oc-heading--sm">
|
|
41
|
-
<h2 class="oc-heading-title">{{ scanTitle }}</h2>
|
|
42
|
-
<p v-if="scanText" class="oc-heading-description">{{ scanText }}</p>
|
|
43
|
-
</div>
|
|
44
|
-
<div class="oc-block-twofactor-center">
|
|
45
|
-
<slot name="qr"><div class="oc-block-twofactor-qr" role="img" aria-label="QR code">QR code</div></slot>
|
|
46
|
-
<OcCopyField :value="setupKey" label="Setup key" />
|
|
47
|
-
</div>
|
|
48
|
-
</section>
|
|
49
|
-
<section class="oc-block-twofactor-step">
|
|
50
|
-
<div class="oc-heading oc-heading--sm"><h2 class="oc-heading-title">{{ confirmTitle }}</h2></div>
|
|
51
|
-
<div class="oc-field">
|
|
52
|
-
<label class="oc-field-label" :for="codeId">{{ codeLabel }}</label>
|
|
53
|
-
<OcOtpInput :id="codeId" v-model="code" name="code" :length="length" />
|
|
54
|
-
</div>
|
|
55
|
-
<button class="oc-btn" type="submit" @click="$emit('submit', code)">{{ submitLabel }}</button>
|
|
56
|
-
</section>
|
|
57
|
-
<section v-if="recoveryCodes?.length" class="oc-block-twofactor-step">
|
|
58
|
-
<OcRecoveryCodes :codes="recoveryCodes" />
|
|
59
|
-
</section>
|
|
60
|
-
</div>
|
|
61
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Authenticator setup: QR, copyable key, OTP code and recovery codes. v-model = the typed code.
|
|
4
|
+
* Emits `submit` with the code (form submit of the confirm step). Slot `qr` replaces the QR placeholder.
|
|
5
|
+
* Classes: .oc-block-twofactor, -step, -center, -qr; reuses copy-field, otp, recovery-codes components.
|
|
6
|
+
*/
|
|
7
|
+
import OcCopyField from '../components/OcCopyField.vue'
|
|
8
|
+
import OcOtpInput from '../components/OcOtpInput.vue'
|
|
9
|
+
import OcRecoveryCodes from '../components/OcRecoveryCodes.vue'
|
|
10
|
+
import { useUid } from '../composables/useUid'
|
|
11
|
+
|
|
12
|
+
withDefaults(
|
|
13
|
+
defineProps<{
|
|
14
|
+
setupKey: string
|
|
15
|
+
recoveryCodes?: string[]
|
|
16
|
+
length?: number
|
|
17
|
+
scanTitle?: string
|
|
18
|
+
scanText?: string
|
|
19
|
+
confirmTitle?: string
|
|
20
|
+
codeLabel?: string
|
|
21
|
+
submitLabel?: string
|
|
22
|
+
}>(),
|
|
23
|
+
{
|
|
24
|
+
length: 6,
|
|
25
|
+
scanTitle: '1. Scan the QR code',
|
|
26
|
+
scanText: 'Use an authenticator app, or enter the key manually.',
|
|
27
|
+
confirmTitle: '2. Confirm with a code',
|
|
28
|
+
codeLabel: 'Authentication code',
|
|
29
|
+
submitLabel: 'Enable two-factor',
|
|
30
|
+
},
|
|
31
|
+
)
|
|
32
|
+
defineEmits<{ submit: [code: string] }>()
|
|
33
|
+
const code = defineModel<string>({ default: '' })
|
|
34
|
+
const codeId = useUid('oc-twofactor-code')
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<template>
|
|
38
|
+
<div class="oc-block-twofactor">
|
|
39
|
+
<section class="oc-block-twofactor-step">
|
|
40
|
+
<div class="oc-heading oc-heading--sm">
|
|
41
|
+
<h2 class="oc-heading-title">{{ scanTitle }}</h2>
|
|
42
|
+
<p v-if="scanText" class="oc-heading-description">{{ scanText }}</p>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="oc-block-twofactor-center">
|
|
45
|
+
<slot name="qr"><div class="oc-block-twofactor-qr" role="img" aria-label="QR code">QR code</div></slot>
|
|
46
|
+
<OcCopyField :value="setupKey" label="Setup key" />
|
|
47
|
+
</div>
|
|
48
|
+
</section>
|
|
49
|
+
<section class="oc-block-twofactor-step">
|
|
50
|
+
<div class="oc-heading oc-heading--sm"><h2 class="oc-heading-title">{{ confirmTitle }}</h2></div>
|
|
51
|
+
<div class="oc-field">
|
|
52
|
+
<label class="oc-field-label" :for="codeId">{{ codeLabel }}</label>
|
|
53
|
+
<OcOtpInput :id="codeId" v-model="code" name="code" :length="length" />
|
|
54
|
+
</div>
|
|
55
|
+
<button class="oc-btn" type="submit" @click="$emit('submit', code)">{{ submitLabel }}</button>
|
|
56
|
+
</section>
|
|
57
|
+
<section v-if="recoveryCodes?.length" class="oc-block-twofactor-step">
|
|
58
|
+
<OcRecoveryCodes :codes="recoveryCodes" />
|
|
59
|
+
</section>
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|