@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,28 +1,28 @@
|
|
|
1
|
-
<!-- File: packages/vue/src/components/OcToggleField.vue | Map: props + model -> template (label row: text + span.oc-switch) -->
|
|
2
|
-
<script setup lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* Settings row: title, description and a switch. v-model: boolean. Slots `label` / `description` override the props.
|
|
5
|
-
* Same markup as packages/ui/snippets/toggle-field.html. class/style on the row, other attributes on the checkbox.
|
|
6
|
-
*/
|
|
7
|
-
import { useAttrsSplit } from '../composables/useAttrsSplit'
|
|
8
|
-
import { useUid } from '../composables/useUid'
|
|
9
|
-
|
|
10
|
-
defineOptions({ inheritAttrs: false })
|
|
11
|
-
defineProps<{ label?: string; description?: string; card?: boolean; reverse?: boolean }>()
|
|
12
|
-
const model = defineModel<boolean>({ default: false })
|
|
13
|
-
const { root, control } = useAttrsSplit()
|
|
14
|
-
const descId = useUid('oc-toggle-field')
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<template>
|
|
18
|
-
<label v-bind="root" :class="['oc-toggle-field', card && 'oc-toggle-field--card', reverse && 'oc-toggle-field--reverse']">
|
|
19
|
-
<span class="oc-toggle-field-text">
|
|
20
|
-
<span class="oc-toggle-field-label"><slot name="label">{{ label }}</slot></span>
|
|
21
|
-
<span v-if="description || $slots.description" :id="descId" class="oc-toggle-field-description"><slot name="description">{{ description }}</slot></span>
|
|
22
|
-
</span>
|
|
23
|
-
<span class="oc-switch">
|
|
24
|
-
<input v-bind="control" v-model="model" type="checkbox" role="switch" :aria-describedby="description || $slots.description ? descId : undefined" />
|
|
25
|
-
<span class="oc-switch-track"></span>
|
|
26
|
-
</span>
|
|
27
|
-
</label>
|
|
28
|
-
</template>
|
|
1
|
+
<!-- File: packages/vue/src/components/OcToggleField.vue | Map: props + model -> template (label row: text + span.oc-switch) -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* Settings row: title, description and a switch. v-model: boolean. Slots `label` / `description` override the props.
|
|
5
|
+
* Same markup as packages/ui/snippets/toggle-field.html. class/style on the row, other attributes on the checkbox.
|
|
6
|
+
*/
|
|
7
|
+
import { useAttrsSplit } from '../composables/useAttrsSplit'
|
|
8
|
+
import { useUid } from '../composables/useUid'
|
|
9
|
+
|
|
10
|
+
defineOptions({ inheritAttrs: false })
|
|
11
|
+
defineProps<{ label?: string; description?: string; card?: boolean; reverse?: boolean }>()
|
|
12
|
+
const model = defineModel<boolean>({ default: false })
|
|
13
|
+
const { root, control } = useAttrsSplit()
|
|
14
|
+
const descId = useUid('oc-toggle-field')
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<label v-bind="root" :class="['oc-toggle-field', card && 'oc-toggle-field--card', reverse && 'oc-toggle-field--reverse']">
|
|
19
|
+
<span class="oc-toggle-field-text">
|
|
20
|
+
<span class="oc-toggle-field-label"><slot name="label">{{ label }}</slot></span>
|
|
21
|
+
<span v-if="description || $slots.description" :id="descId" class="oc-toggle-field-description"><slot name="description">{{ description }}</slot></span>
|
|
22
|
+
</span>
|
|
23
|
+
<span class="oc-switch">
|
|
24
|
+
<input v-bind="control" v-model="model" type="checkbox" role="switch" :aria-describedby="description || $slots.description ? descId : undefined" />
|
|
25
|
+
<span class="oc-switch-track"></span>
|
|
26
|
+
</span>
|
|
27
|
+
</label>
|
|
28
|
+
</template>
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/**
|
|
3
|
-
* Connected toggles. v-model = array of pressed values (type "multiple", checkbox inputs) or a single value
|
|
4
|
-
* string (type "single", radio inputs). Put OcToggle items with a `value` inside.
|
|
5
|
-
* Classes: .oc-toggle-group(--spaced)
|
|
6
|
-
*/
|
|
7
|
-
import { computed, provide } from 'vue'
|
|
8
|
-
import { useUid } from '../composables/useUid'
|
|
9
|
-
import { toggleGroupKey } from '../composables/keys'
|
|
10
|
-
|
|
11
|
-
const props = withDefaults(defineProps<{ type?: 'single' | 'multiple'; spaced?: boolean; label?: string; name?: string }>(), { type: 'multiple' })
|
|
12
|
-
const model = defineModel<string | string[]>()
|
|
13
|
-
const uid = useUid('oc-toggle')
|
|
14
|
-
|
|
15
|
-
const values = computed(() => (Array.isArray(model.value) ? model.value : model.value ? [model.value] : []))
|
|
16
|
-
function toggle(value: string) {
|
|
17
|
-
if (props.type === 'single') {
|
|
18
|
-
model.value = value
|
|
19
|
-
} else {
|
|
20
|
-
const list = values.value
|
|
21
|
-
model.value = list.includes(value) ? list.filter((v) => v !== value) : [...list, value]
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
provide(toggleGroupKey, {
|
|
25
|
-
values,
|
|
26
|
-
type: computed(() => props.type),
|
|
27
|
-
name: computed(() => props.name ?? uid),
|
|
28
|
-
toggle,
|
|
29
|
-
})
|
|
30
|
-
</script>
|
|
31
|
-
|
|
32
|
-
<template>
|
|
33
|
-
<div
|
|
34
|
-
:class="['oc-toggle-group', spaced && 'oc-toggle-group--spaced']"
|
|
35
|
-
:role="type === 'single' ? 'radiogroup' : 'group'"
|
|
36
|
-
:aria-label="label"
|
|
37
|
-
>
|
|
38
|
-
<slot />
|
|
39
|
-
</div>
|
|
40
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Connected toggles. v-model = array of pressed values (type "multiple", checkbox inputs) or a single value
|
|
4
|
+
* string (type "single", radio inputs). Put OcToggle items with a `value` inside.
|
|
5
|
+
* Classes: .oc-toggle-group(--spaced)
|
|
6
|
+
*/
|
|
7
|
+
import { computed, provide } from 'vue'
|
|
8
|
+
import { useUid } from '../composables/useUid'
|
|
9
|
+
import { toggleGroupKey } from '../composables/keys'
|
|
10
|
+
|
|
11
|
+
const props = withDefaults(defineProps<{ type?: 'single' | 'multiple'; spaced?: boolean; label?: string; name?: string }>(), { type: 'multiple' })
|
|
12
|
+
const model = defineModel<string | string[]>()
|
|
13
|
+
const uid = useUid('oc-toggle')
|
|
14
|
+
|
|
15
|
+
const values = computed(() => (Array.isArray(model.value) ? model.value : model.value ? [model.value] : []))
|
|
16
|
+
function toggle(value: string) {
|
|
17
|
+
if (props.type === 'single') {
|
|
18
|
+
model.value = value
|
|
19
|
+
} else {
|
|
20
|
+
const list = values.value
|
|
21
|
+
model.value = list.includes(value) ? list.filter((v) => v !== value) : [...list, value]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
provide(toggleGroupKey, {
|
|
25
|
+
values,
|
|
26
|
+
type: computed(() => props.type),
|
|
27
|
+
name: computed(() => props.name ?? uid),
|
|
28
|
+
toggle,
|
|
29
|
+
})
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<div
|
|
34
|
+
:class="['oc-toggle-group', spaced && 'oc-toggle-group--spaced']"
|
|
35
|
+
:role="type === 'single' ? 'radiogroup' : 'group'"
|
|
36
|
+
:aria-label="label"
|
|
37
|
+
>
|
|
38
|
+
<slot />
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/** CSS-only tooltip: wraps the default slot and shows `text` via data-tooltip. */
|
|
3
|
-
defineProps<{ text: string }>()
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<template>
|
|
7
|
-
<span class="oc-tooltip" :data-tooltip="text"><slot /></span>
|
|
8
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** CSS-only tooltip: wraps the default slot and shows `text` via data-tooltip. */
|
|
3
|
+
defineProps<{ text: string }>()
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<span class="oc-tooltip" :data-tooltip="text"><slot /></span>
|
|
8
|
+
</template>
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
<!-- File: packages/vue/src/components/OcTopProgress.vue | Map: progress.oc-top-progress -> phase (hidden / active / done) -> fade-out timer -->
|
|
2
|
-
<script setup lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* Thin page-top loading bar. `active` shows it; when `active` turns false the bar fades out (.is-done)
|
|
5
|
-
* and is hidden after `fadeMs`. Without `value` it is indeterminate.
|
|
6
|
-
* Classes: progress.oc-top-progress(--success/--warning/--danger/--brand/--lg/--static), .is-done, [hidden]
|
|
7
|
-
*/
|
|
8
|
-
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
|
9
|
-
|
|
10
|
-
const props = withDefaults(
|
|
11
|
-
defineProps<{
|
|
12
|
-
active?: boolean
|
|
13
|
-
value?: number
|
|
14
|
-
max?: number
|
|
15
|
-
tone?: 'default' | 'success' | 'warning' | 'danger' | 'brand'
|
|
16
|
-
large?: boolean
|
|
17
|
-
/** In the normal flow (inside a card) instead of fixed at the top. */
|
|
18
|
-
static?: boolean
|
|
19
|
-
fadeMs?: number
|
|
20
|
-
}>(),
|
|
21
|
-
{ active: true, tone: 'default', fadeMs: 400, value: undefined, max: undefined },
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
const phase = ref<'hidden' | 'active' | 'done'>(props.active ? 'active' : 'hidden')
|
|
25
|
-
let timer: ReturnType<typeof setTimeout> | undefined
|
|
26
|
-
|
|
27
|
-
watch(
|
|
28
|
-
() => props.active,
|
|
29
|
-
(on) => {
|
|
30
|
-
clearTimeout(timer)
|
|
31
|
-
if (on) {
|
|
32
|
-
phase.value = 'active'
|
|
33
|
-
return
|
|
34
|
-
}
|
|
35
|
-
// Only fade out when the bar was visible.
|
|
36
|
-
if (phase.value === 'hidden') return
|
|
37
|
-
phase.value = 'done'
|
|
38
|
-
timer = setTimeout(() => (phase.value = 'hidden'), props.fadeMs)
|
|
39
|
-
},
|
|
40
|
-
)
|
|
41
|
-
onBeforeUnmount(() => clearTimeout(timer))
|
|
42
|
-
|
|
43
|
-
const classes = computed(() => [
|
|
44
|
-
'oc-top-progress',
|
|
45
|
-
props.tone !== 'default' && `oc-top-progress--${props.tone}`,
|
|
46
|
-
props.large && 'oc-top-progress--lg',
|
|
47
|
-
props.static && 'oc-top-progress--static',
|
|
48
|
-
phase.value === 'done' && 'is-done',
|
|
49
|
-
])
|
|
50
|
-
</script>
|
|
51
|
-
|
|
52
|
-
<template>
|
|
53
|
-
<progress :class="classes" :value="value" :max="max" :hidden="phase === 'hidden'"></progress>
|
|
54
|
-
</template>
|
|
1
|
+
<!-- File: packages/vue/src/components/OcTopProgress.vue | Map: progress.oc-top-progress -> phase (hidden / active / done) -> fade-out timer -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* Thin page-top loading bar. `active` shows it; when `active` turns false the bar fades out (.is-done)
|
|
5
|
+
* and is hidden after `fadeMs`. Without `value` it is indeterminate.
|
|
6
|
+
* Classes: progress.oc-top-progress(--success/--warning/--danger/--brand/--lg/--static), .is-done, [hidden]
|
|
7
|
+
*/
|
|
8
|
+
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(
|
|
11
|
+
defineProps<{
|
|
12
|
+
active?: boolean
|
|
13
|
+
value?: number
|
|
14
|
+
max?: number
|
|
15
|
+
tone?: 'default' | 'success' | 'warning' | 'danger' | 'brand'
|
|
16
|
+
large?: boolean
|
|
17
|
+
/** In the normal flow (inside a card) instead of fixed at the top. */
|
|
18
|
+
static?: boolean
|
|
19
|
+
fadeMs?: number
|
|
20
|
+
}>(),
|
|
21
|
+
{ active: true, tone: 'default', fadeMs: 400, value: undefined, max: undefined },
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const phase = ref<'hidden' | 'active' | 'done'>(props.active ? 'active' : 'hidden')
|
|
25
|
+
let timer: ReturnType<typeof setTimeout> | undefined
|
|
26
|
+
|
|
27
|
+
watch(
|
|
28
|
+
() => props.active,
|
|
29
|
+
(on) => {
|
|
30
|
+
clearTimeout(timer)
|
|
31
|
+
if (on) {
|
|
32
|
+
phase.value = 'active'
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
// Only fade out when the bar was visible.
|
|
36
|
+
if (phase.value === 'hidden') return
|
|
37
|
+
phase.value = 'done'
|
|
38
|
+
timer = setTimeout(() => (phase.value = 'hidden'), props.fadeMs)
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
onBeforeUnmount(() => clearTimeout(timer))
|
|
42
|
+
|
|
43
|
+
const classes = computed(() => [
|
|
44
|
+
'oc-top-progress',
|
|
45
|
+
props.tone !== 'default' && `oc-top-progress--${props.tone}`,
|
|
46
|
+
props.large && 'oc-top-progress--lg',
|
|
47
|
+
props.static && 'oc-top-progress--static',
|
|
48
|
+
phase.value === 'done' && 'is-done',
|
|
49
|
+
])
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<progress :class="classes" :value="value" :max="max" :hidden="phase === 'hidden'"></progress>
|
|
54
|
+
</template>
|
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
<!-- File: packages/vue/src/components/OcTree.vue | Map: box (+ head row) -> list -> item: folder (details/summary + nested OcTree) or leaf (div row) -->
|
|
2
|
-
<script setup lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* Nested tree list on details / summary. Renders itself recursively for child lists (`nested`).
|
|
5
|
-
* Slots (scoped, { item }): icon, actions; plus `head-actions` for the head row.
|
|
6
|
-
* Classes: .oc-tree(--quiet/--flush), .oc-tree-head, ul.oc-tree-list, details.oc-tree-node, .oc-tree-row(.is-muted),
|
|
7
|
-
* .oc-tree-icon, .oc-tree-label, .oc-tree-count, .oc-tree-actions
|
|
8
|
-
*/
|
|
9
|
-
export interface OcTreeItem {
|
|
10
|
-
label: string
|
|
11
|
-
href?: string
|
|
12
|
-
count?: string | number
|
|
13
|
-
children?: OcTreeItem[]
|
|
14
|
-
open?: boolean
|
|
15
|
-
current?: boolean
|
|
16
|
-
muted?: boolean
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
defineOptions({ name: 'OcTree' })
|
|
20
|
-
defineProps<{
|
|
21
|
-
items: OcTreeItem[]
|
|
22
|
-
head?: string
|
|
23
|
-
quiet?: boolean
|
|
24
|
-
flush?: boolean
|
|
25
|
-
/** Internal: render only the list (used for child lists). */
|
|
26
|
-
nested?: boolean
|
|
27
|
-
}>()
|
|
28
|
-
// Typed slots: the component renders itself, so TypeScript cannot infer these on its own.
|
|
29
|
-
defineSlots<{
|
|
30
|
-
icon?(props: { item: OcTreeItem }): unknown
|
|
31
|
-
actions?(props: { item: OcTreeItem }): unknown
|
|
32
|
-
'head-actions'?(): unknown
|
|
33
|
-
}>()
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
<template>
|
|
37
|
-
<ul v-if="nested" class="oc-tree-list">
|
|
38
|
-
<li v-for="(item, i) in items" :key="i">
|
|
39
|
-
<details v-if="item.children?.length" class="oc-tree-node" :open="item.open">
|
|
40
|
-
<summary :class="['oc-tree-row', item.muted && 'is-muted']" :aria-current="item.current && !item.href ? 'true' : undefined">
|
|
41
|
-
<span v-if="$slots.icon" class="oc-tree-icon" aria-hidden="true"><slot name="icon" :item="item" /></span>
|
|
42
|
-
<span class="oc-tree-label">{{ item.label }}</span>
|
|
43
|
-
<span v-if="item.count != null" class="oc-tree-count">{{ item.count }}</span>
|
|
44
|
-
<span v-if="$slots.actions" class="oc-tree-actions"><slot name="actions" :item="item" /></span>
|
|
45
|
-
</summary>
|
|
46
|
-
<OcTree :items="item.children" nested>
|
|
47
|
-
<template v-if="$slots.icon" #icon="{ item: child }"><slot name="icon" :item="child" /></template>
|
|
48
|
-
<template v-if="$slots.actions" #actions="{ item: child }"><slot name="actions" :item="child" /></template>
|
|
49
|
-
</OcTree>
|
|
50
|
-
</details>
|
|
51
|
-
<div v-else :class="['oc-tree-row', item.muted && 'is-muted']" :aria-current="item.current && !item.href ? 'true' : undefined">
|
|
52
|
-
<span v-if="$slots.icon" class="oc-tree-icon" aria-hidden="true"><slot name="icon" :item="item" /></span>
|
|
53
|
-
<a v-if="item.href" class="oc-tree-label" :href="item.href" :aria-current="item.current ? 'true' : undefined">{{ item.label }}</a>
|
|
54
|
-
<span v-else class="oc-tree-label">{{ item.label }}</span>
|
|
55
|
-
<span v-if="item.count != null" class="oc-tree-count">{{ item.count }}</span>
|
|
56
|
-
<span v-if="$slots.actions" class="oc-tree-actions"><slot name="actions" :item="item" /></span>
|
|
57
|
-
</div>
|
|
58
|
-
</li>
|
|
59
|
-
</ul>
|
|
60
|
-
<div v-else :class="['oc-tree', quiet && 'oc-tree--quiet', flush && 'oc-tree--flush']">
|
|
61
|
-
<div v-if="head" class="oc-tree-row oc-tree-head">
|
|
62
|
-
<span class="oc-tree-label">{{ head }}</span>
|
|
63
|
-
<span v-if="$slots['head-actions']" class="oc-tree-actions"><slot name="head-actions" /></span>
|
|
64
|
-
</div>
|
|
65
|
-
<OcTree :items="items" nested>
|
|
66
|
-
<template v-if="$slots.icon" #icon="{ item: child }"><slot name="icon" :item="child" /></template>
|
|
67
|
-
<template v-if="$slots.actions" #actions="{ item: child }"><slot name="actions" :item="child" /></template>
|
|
68
|
-
</OcTree>
|
|
69
|
-
</div>
|
|
70
|
-
</template>
|
|
1
|
+
<!-- File: packages/vue/src/components/OcTree.vue | Map: box (+ head row) -> list -> item: folder (details/summary + nested OcTree) or leaf (div row) -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* Nested tree list on details / summary. Renders itself recursively for child lists (`nested`).
|
|
5
|
+
* Slots (scoped, { item }): icon, actions; plus `head-actions` for the head row.
|
|
6
|
+
* Classes: .oc-tree(--quiet/--flush), .oc-tree-head, ul.oc-tree-list, details.oc-tree-node, .oc-tree-row(.is-muted),
|
|
7
|
+
* .oc-tree-icon, .oc-tree-label, .oc-tree-count, .oc-tree-actions
|
|
8
|
+
*/
|
|
9
|
+
export interface OcTreeItem {
|
|
10
|
+
label: string
|
|
11
|
+
href?: string
|
|
12
|
+
count?: string | number
|
|
13
|
+
children?: OcTreeItem[]
|
|
14
|
+
open?: boolean
|
|
15
|
+
current?: boolean
|
|
16
|
+
muted?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
defineOptions({ name: 'OcTree' })
|
|
20
|
+
defineProps<{
|
|
21
|
+
items: OcTreeItem[]
|
|
22
|
+
head?: string
|
|
23
|
+
quiet?: boolean
|
|
24
|
+
flush?: boolean
|
|
25
|
+
/** Internal: render only the list (used for child lists). */
|
|
26
|
+
nested?: boolean
|
|
27
|
+
}>()
|
|
28
|
+
// Typed slots: the component renders itself, so TypeScript cannot infer these on its own.
|
|
29
|
+
defineSlots<{
|
|
30
|
+
icon?(props: { item: OcTreeItem }): unknown
|
|
31
|
+
actions?(props: { item: OcTreeItem }): unknown
|
|
32
|
+
'head-actions'?(): unknown
|
|
33
|
+
}>()
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<template>
|
|
37
|
+
<ul v-if="nested" class="oc-tree-list">
|
|
38
|
+
<li v-for="(item, i) in items" :key="i">
|
|
39
|
+
<details v-if="item.children?.length" class="oc-tree-node" :open="item.open">
|
|
40
|
+
<summary :class="['oc-tree-row', item.muted && 'is-muted']" :aria-current="item.current && !item.href ? 'true' : undefined">
|
|
41
|
+
<span v-if="$slots.icon" class="oc-tree-icon" aria-hidden="true"><slot name="icon" :item="item" /></span>
|
|
42
|
+
<span class="oc-tree-label">{{ item.label }}</span>
|
|
43
|
+
<span v-if="item.count != null" class="oc-tree-count">{{ item.count }}</span>
|
|
44
|
+
<span v-if="$slots.actions" class="oc-tree-actions"><slot name="actions" :item="item" /></span>
|
|
45
|
+
</summary>
|
|
46
|
+
<OcTree :items="item.children" nested>
|
|
47
|
+
<template v-if="$slots.icon" #icon="{ item: child }"><slot name="icon" :item="child" /></template>
|
|
48
|
+
<template v-if="$slots.actions" #actions="{ item: child }"><slot name="actions" :item="child" /></template>
|
|
49
|
+
</OcTree>
|
|
50
|
+
</details>
|
|
51
|
+
<div v-else :class="['oc-tree-row', item.muted && 'is-muted']" :aria-current="item.current && !item.href ? 'true' : undefined">
|
|
52
|
+
<span v-if="$slots.icon" class="oc-tree-icon" aria-hidden="true"><slot name="icon" :item="item" /></span>
|
|
53
|
+
<a v-if="item.href" class="oc-tree-label" :href="item.href" :aria-current="item.current ? 'true' : undefined">{{ item.label }}</a>
|
|
54
|
+
<span v-else class="oc-tree-label">{{ item.label }}</span>
|
|
55
|
+
<span v-if="item.count != null" class="oc-tree-count">{{ item.count }}</span>
|
|
56
|
+
<span v-if="$slots.actions" class="oc-tree-actions"><slot name="actions" :item="item" /></span>
|
|
57
|
+
</div>
|
|
58
|
+
</li>
|
|
59
|
+
</ul>
|
|
60
|
+
<div v-else :class="['oc-tree', quiet && 'oc-tree--quiet', flush && 'oc-tree--flush']">
|
|
61
|
+
<div v-if="head" class="oc-tree-row oc-tree-head">
|
|
62
|
+
<span class="oc-tree-label">{{ head }}</span>
|
|
63
|
+
<span v-if="$slots['head-actions']" class="oc-tree-actions"><slot name="head-actions" /></span>
|
|
64
|
+
</div>
|
|
65
|
+
<OcTree :items="items" nested>
|
|
66
|
+
<template v-if="$slots.icon" #icon="{ item: child }"><slot name="icon" :item="child" /></template>
|
|
67
|
+
<template v-if="$slots.actions" #actions="{ item: child }"><slot name="actions" :item="child" /></template>
|
|
68
|
+
</OcTree>
|
|
69
|
+
</div>
|
|
70
|
+
</template>
|
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
<!-- File: packages/vue/src/components/OcUpgradeBanner.vue | Map: aside -> icon slot -> body (title + plan pill, text slot, usage meter) -> actions slot -> dismiss button -->
|
|
2
|
-
<script setup lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* Free-plan limits callout. `dismissible` adds an X that emits `dismiss` (your app hides the banner).
|
|
5
|
-
* Slots: icon, default (text, may hold links), actions.
|
|
6
|
-
* Classes: .oc-upgrade-banner(--premium/--compact), -icon, -body, -title, -plan, -text, -usage, meter.oc-upgrade-banner-meter, -actions, -dismiss
|
|
7
|
-
*/
|
|
8
|
-
withDefaults(
|
|
9
|
-
defineProps<{
|
|
10
|
-
title: string
|
|
11
|
-
plan?: string
|
|
12
|
-
text?: string
|
|
13
|
-
usage?: { label: string; value: number; max: number }
|
|
14
|
-
premium?: boolean
|
|
15
|
-
compact?: boolean
|
|
16
|
-
dismissible?: boolean
|
|
17
|
-
dismissLabel?: string
|
|
18
|
-
}>(),
|
|
19
|
-
{ dismissLabel: 'Dismiss' },
|
|
20
|
-
)
|
|
21
|
-
const emit = defineEmits<{ dismiss: [] }>()
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<template>
|
|
25
|
-
<aside :class="['oc-upgrade-banner', premium && 'oc-upgrade-banner--premium', compact && 'oc-upgrade-banner--compact']">
|
|
26
|
-
<span v-if="$slots.icon" class="oc-upgrade-banner-icon" aria-hidden="true"><slot name="icon" /></span>
|
|
27
|
-
<div class="oc-upgrade-banner-body">
|
|
28
|
-
<p class="oc-upgrade-banner-title">{{ title }} <span v-if="plan" class="oc-upgrade-banner-plan">{{ plan }}</span></p>
|
|
29
|
-
<p v-if="$slots.default || text" class="oc-upgrade-banner-text"><slot>{{ text }}</slot></p>
|
|
30
|
-
<div v-if="usage" class="oc-upgrade-banner-usage">
|
|
31
|
-
<span>{{ usage.label }}</span>
|
|
32
|
-
<!-- low / high make the meter turn "less good" near the limit. -->
|
|
33
|
-
<meter class="oc-upgrade-banner-meter" min="0" :max="usage.max" :low="usage.max * 0.6" :high="usage.max * 0.8" optimum="0" :value="usage.value">
|
|
34
|
-
{{ usage.value }} of {{ usage.max }}
|
|
35
|
-
</meter>
|
|
36
|
-
<span>{{ usage.value }} / {{ usage.max }}</span>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
<div v-if="$slots.actions" class="oc-upgrade-banner-actions"><slot name="actions" /></div>
|
|
40
|
-
<button v-if="dismissible" class="oc-upgrade-banner-dismiss" type="button" :aria-label="dismissLabel" @click="emit('dismiss')">×</button>
|
|
41
|
-
</aside>
|
|
42
|
-
</template>
|
|
1
|
+
<!-- File: packages/vue/src/components/OcUpgradeBanner.vue | Map: aside -> icon slot -> body (title + plan pill, text slot, usage meter) -> actions slot -> dismiss button -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* Free-plan limits callout. `dismissible` adds an X that emits `dismiss` (your app hides the banner).
|
|
5
|
+
* Slots: icon, default (text, may hold links), actions.
|
|
6
|
+
* Classes: .oc-upgrade-banner(--premium/--compact), -icon, -body, -title, -plan, -text, -usage, meter.oc-upgrade-banner-meter, -actions, -dismiss
|
|
7
|
+
*/
|
|
8
|
+
withDefaults(
|
|
9
|
+
defineProps<{
|
|
10
|
+
title: string
|
|
11
|
+
plan?: string
|
|
12
|
+
text?: string
|
|
13
|
+
usage?: { label: string; value: number; max: number }
|
|
14
|
+
premium?: boolean
|
|
15
|
+
compact?: boolean
|
|
16
|
+
dismissible?: boolean
|
|
17
|
+
dismissLabel?: string
|
|
18
|
+
}>(),
|
|
19
|
+
{ dismissLabel: 'Dismiss' },
|
|
20
|
+
)
|
|
21
|
+
const emit = defineEmits<{ dismiss: [] }>()
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<aside :class="['oc-upgrade-banner', premium && 'oc-upgrade-banner--premium', compact && 'oc-upgrade-banner--compact']">
|
|
26
|
+
<span v-if="$slots.icon" class="oc-upgrade-banner-icon" aria-hidden="true"><slot name="icon" /></span>
|
|
27
|
+
<div class="oc-upgrade-banner-body">
|
|
28
|
+
<p class="oc-upgrade-banner-title">{{ title }} <span v-if="plan" class="oc-upgrade-banner-plan">{{ plan }}</span></p>
|
|
29
|
+
<p v-if="$slots.default || text" class="oc-upgrade-banner-text"><slot>{{ text }}</slot></p>
|
|
30
|
+
<div v-if="usage" class="oc-upgrade-banner-usage">
|
|
31
|
+
<span>{{ usage.label }}</span>
|
|
32
|
+
<!-- low / high make the meter turn "less good" near the limit. -->
|
|
33
|
+
<meter class="oc-upgrade-banner-meter" min="0" :max="usage.max" :low="usage.max * 0.6" :high="usage.max * 0.8" optimum="0" :value="usage.value">
|
|
34
|
+
{{ usage.value }} of {{ usage.max }}
|
|
35
|
+
</meter>
|
|
36
|
+
<span>{{ usage.value }} / {{ usage.max }}</span>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
<div v-if="$slots.actions" class="oc-upgrade-banner-actions"><slot name="actions" /></div>
|
|
40
|
+
<button v-if="dismissible" class="oc-upgrade-banner-dismiss" type="button" :aria-label="dismissLabel" @click="emit('dismiss')">×</button>
|
|
41
|
+
</aside>
|
|
42
|
+
</template>
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
/** Avatar with name and e-mail (truncating). `initials` or `src` fill the avatar; slot `avatar` replaces it. */
|
|
3
|
-
defineProps<{
|
|
4
|
-
name: string
|
|
5
|
-
email?: string
|
|
6
|
-
initials?: string
|
|
7
|
-
src?: string
|
|
8
|
-
avatarSize?: 'sm' | 'md' | 'lg' | 'xl'
|
|
9
|
-
}>()
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
<template>
|
|
13
|
-
<div class="oc-user">
|
|
14
|
-
<slot name="avatar">
|
|
15
|
-
<span :class="['oc-avatar', avatarSize && avatarSize !== 'md' && `oc-avatar--${avatarSize}`]">
|
|
16
|
-
<img v-if="src" :src="src" alt="" />
|
|
17
|
-
<template v-else>{{ initials }}</template>
|
|
18
|
-
</span>
|
|
19
|
-
</slot>
|
|
20
|
-
<span class="oc-user-text">
|
|
21
|
-
<span class="oc-user-name">{{ name }}</span>
|
|
22
|
-
<span v-if="email" class="oc-user-email">{{ email }}</span>
|
|
23
|
-
</span>
|
|
24
|
-
</div>
|
|
25
|
-
</template>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Avatar with name and e-mail (truncating). `initials` or `src` fill the avatar; slot `avatar` replaces it. */
|
|
3
|
+
defineProps<{
|
|
4
|
+
name: string
|
|
5
|
+
email?: string
|
|
6
|
+
initials?: string
|
|
7
|
+
src?: string
|
|
8
|
+
avatarSize?: 'sm' | 'md' | 'lg' | 'xl'
|
|
9
|
+
}>()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div class="oc-user">
|
|
14
|
+
<slot name="avatar">
|
|
15
|
+
<span :class="['oc-avatar', avatarSize && avatarSize !== 'md' && `oc-avatar--${avatarSize}`]">
|
|
16
|
+
<img v-if="src" :src="src" alt="" />
|
|
17
|
+
<template v-else>{{ initials }}</template>
|
|
18
|
+
</span>
|
|
19
|
+
</slot>
|
|
20
|
+
<span class="oc-user-text">
|
|
21
|
+
<span class="oc-user-name">{{ name }}</span>
|
|
22
|
+
<span v-if="email" class="oc-user-email">{{ email }}</span>
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
<!-- File: packages/vue/src/components/OcVersionBanner.vue | Map: chip (role=status) -> dot -> long text -> short text -> reload action -->
|
|
2
|
-
<script setup lang="ts">
|
|
3
|
-
/**
|
|
4
|
-
* "New version available - reload" chip. Renders nothing while `version` is empty.
|
|
5
|
-
* Without an @reload listener the action is a plain link to the current page; with one it is a button.
|
|
6
|
-
* Slots: default (long text). Classes: .oc-version-banner(--info/--success/--floating), -dot, -text, -short, -action
|
|
7
|
-
*/
|
|
8
|
-
const props = withDefaults(
|
|
9
|
-
defineProps<{
|
|
10
|
-
version?: string | null
|
|
11
|
-
short?: string
|
|
12
|
-
actionLabel?: string
|
|
13
|
-
tone?: 'warning' | 'info' | 'success'
|
|
14
|
-
floating?: boolean
|
|
15
|
-
/** Declared as a prop so the component can see whether a listener is set. */
|
|
16
|
-
onReload?: () => void
|
|
17
|
-
}>(),
|
|
18
|
-
{ short: 'New version', actionLabel: 'Reload', tone: 'warning', version: null, onReload: undefined },
|
|
19
|
-
)
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<template>
|
|
23
|
-
<div
|
|
24
|
-
v-if="version"
|
|
25
|
-
:class="['oc-version-banner', tone !== 'warning' && `oc-version-banner--${tone}`, floating && 'oc-version-banner--floating']"
|
|
26
|
-
role="status"
|
|
27
|
-
>
|
|
28
|
-
<span class="oc-version-banner-dot" aria-hidden="true"></span>
|
|
29
|
-
<span class="oc-version-banner-text"><slot>New version ({{ version }}) available - reload the page</slot></span>
|
|
30
|
-
<span class="oc-version-banner-short">{{ short }}</span>
|
|
31
|
-
<button v-if="props.onReload" class="oc-version-banner-action" type="button" @click="props.onReload()">{{ actionLabel }}</button>
|
|
32
|
-
<a v-else class="oc-version-banner-action" href="">{{ actionLabel }}</a>
|
|
33
|
-
</div>
|
|
34
|
-
</template>
|
|
1
|
+
<!-- File: packages/vue/src/components/OcVersionBanner.vue | Map: chip (role=status) -> dot -> long text -> short text -> reload action -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* "New version available - reload" chip. Renders nothing while `version` is empty.
|
|
5
|
+
* Without an @reload listener the action is a plain link to the current page; with one it is a button.
|
|
6
|
+
* Slots: default (long text). Classes: .oc-version-banner(--info/--success/--floating), -dot, -text, -short, -action
|
|
7
|
+
*/
|
|
8
|
+
const props = withDefaults(
|
|
9
|
+
defineProps<{
|
|
10
|
+
version?: string | null
|
|
11
|
+
short?: string
|
|
12
|
+
actionLabel?: string
|
|
13
|
+
tone?: 'warning' | 'info' | 'success'
|
|
14
|
+
floating?: boolean
|
|
15
|
+
/** Declared as a prop so the component can see whether a listener is set. */
|
|
16
|
+
onReload?: () => void
|
|
17
|
+
}>(),
|
|
18
|
+
{ short: 'New version', actionLabel: 'Reload', tone: 'warning', version: null, onReload: undefined },
|
|
19
|
+
)
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<div
|
|
24
|
+
v-if="version"
|
|
25
|
+
:class="['oc-version-banner', tone !== 'warning' && `oc-version-banner--${tone}`, floating && 'oc-version-banner--floating']"
|
|
26
|
+
role="status"
|
|
27
|
+
>
|
|
28
|
+
<span class="oc-version-banner-dot" aria-hidden="true"></span>
|
|
29
|
+
<span class="oc-version-banner-text"><slot>New version ({{ version }}) available - reload the page</slot></span>
|
|
30
|
+
<span class="oc-version-banner-short">{{ short }}</span>
|
|
31
|
+
<button v-if="props.onReload" class="oc-version-banner-action" type="button" @click="props.onReload()">{{ actionLabel }}</button>
|
|
32
|
+
<a v-else class="oc-version-banner-action" href="">{{ actionLabel }}</a>
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|