@birdycom/omniaui-vue 0.0.0-stage → 0.11.0
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 -0
- package/README.md +48 -2
- package/dist/blocks/OcBlockAboutTimeline.vue.d.ts +29 -0
- package/dist/blocks/OcBlockAppHeader.vue.d.ts +33 -0
- package/dist/blocks/OcBlockAppShell.vue.d.ts +33 -0
- package/dist/blocks/OcBlockAuth.vue.d.ts +28 -0
- package/dist/blocks/OcBlockAuthSplit.vue.d.ts +45 -0
- package/dist/blocks/OcBlockContactGrid.vue.d.ts +32 -0
- package/dist/blocks/OcBlockCta.vue.d.ts +17 -0
- package/dist/blocks/OcBlockDataTable.vue.d.ts +33 -0
- package/dist/blocks/OcBlockFaq.vue.d.ts +32 -0
- package/dist/blocks/OcBlockFeatures.vue.d.ts +25 -0
- package/dist/blocks/OcBlockFooter.vue.d.ts +27 -0
- package/dist/blocks/OcBlockFormPage.vue.d.ts +36 -0
- package/dist/blocks/OcBlockHero.vue.d.ts +18 -0
- package/dist/blocks/OcBlockHeroCode.vue.d.ts +32 -0
- package/dist/blocks/OcBlockHeroOrbit.vue.d.ts +36 -0
- package/dist/blocks/OcBlockHeroSplit.vue.d.ts +19 -0
- package/dist/blocks/OcBlockModuleHeader.vue.d.ts +24 -0
- package/dist/blocks/OcBlockPageHero.vue.d.ts +18 -0
- package/dist/blocks/OcBlockPortfolioGrid.vue.d.ts +34 -0
- package/dist/blocks/OcBlockPricing.vue.d.ts +38 -0
- package/dist/blocks/OcBlockProcess.vue.d.ts +18 -0
- package/dist/blocks/OcBlockProductGrid.vue.d.ts +25 -0
- package/dist/blocks/OcBlockProfileHeader.vue.d.ts +36 -0
- package/dist/blocks/OcBlockShowcase.vue.d.ts +23 -0
- package/dist/blocks/OcBlockSiteFooter.vue.d.ts +42 -0
- package/dist/blocks/OcBlockSiteHeader.vue.d.ts +32 -0
- package/dist/blocks/OcBlockSpotlight.vue.d.ts +32 -0
- package/dist/blocks/OcBlockStats.vue.d.ts +10 -0
- package/dist/blocks/OcBlockStatsCounter.vue.d.ts +10 -0
- package/dist/blocks/OcBlockTeamList.vue.d.ts +42 -0
- package/dist/blocks/OcBlockTwoFactor.vue.d.ts +38 -0
- package/dist/blocks/OcBlockWizardDialog.vue.d.ts +52 -0
- package/dist/components/OcAccordion.vue.d.ts +15 -0
- package/dist/components/OcAccordionAccent.vue.d.ts +20 -0
- package/dist/components/OcAccordionItem.vue.d.ts +24 -0
- package/dist/components/OcAffixInput.vue.d.ts +31 -0
- package/dist/components/OcAlert.vue.d.ts +21 -0
- package/dist/components/OcAlertDialog.vue.d.ts +48 -0
- package/dist/components/OcAlphaTabs.vue.d.ts +23 -0
- package/dist/components/OcAspectRatio.vue.d.ts +16 -0
- package/dist/components/OcAttachment.vue.d.ts +26 -0
- package/dist/components/OcAttachmentImage.vue.d.ts +10 -0
- package/dist/components/OcAttachmentList.vue.d.ts +31 -0
- package/dist/components/OcAttachmentThumb.vue.d.ts +16 -0
- package/dist/components/OcAvatar.vue.d.ts +21 -0
- package/dist/components/OcAvatarGroup.vue.d.ts +12 -0
- package/dist/components/OcBackLink.vue.d.ts +18 -0
- package/dist/components/OcBadge.vue.d.ts +18 -0
- package/dist/components/OcBarcodeInput.vue.d.ts +27 -0
- package/dist/components/OcBreadcrumb.vue.d.ts +24 -0
- package/dist/components/OcBrowserFrame.vue.d.ts +35 -0
- package/dist/components/OcBusyOverlay.vue.d.ts +30 -0
- package/dist/components/OcButton.vue.d.ts +31 -0
- package/dist/components/OcButtonGroup.vue.d.ts +17 -0
- package/dist/components/OcButtonGroupText.vue.d.ts +12 -0
- package/dist/components/OcCard.vue.d.ts +27 -0
- package/dist/components/OcChartLine.vue.d.ts +28 -0
- package/dist/components/OcChatComposer.vue.d.ts +33 -0
- package/dist/components/OcCheckbox.vue.d.ts +26 -0
- package/dist/components/OcChecklist.vue.d.ts +32 -0
- package/dist/components/OcChipFilter.vue.d.ts +24 -0
- package/dist/components/OcCollapsible.vue.d.ts +28 -0
- package/dist/components/OcColorField.vue.d.ts +17 -0
- package/dist/components/OcColorSelect.vue.d.ts +24 -0
- package/dist/components/OcColumnMenu.vue.d.ts +31 -0
- package/dist/components/OcCommand.vue.d.ts +28 -0
- package/dist/components/OcConfirmDialog.vue.d.ts +44 -0
- package/dist/components/OcCookieConsent.vue.d.ts +52 -0
- package/dist/components/OcCopyField.vue.d.ts +14 -0
- package/dist/components/OcCounter.vue.d.ts +9 -0
- package/dist/components/OcDataTable.vue.d.ts +37 -0
- package/dist/components/OcDecimalInput.vue.d.ts +19 -0
- package/dist/components/OcDefinitionList.vue.d.ts +34 -0
- package/dist/components/OcDocViewer.vue.d.ts +24 -0
- package/dist/components/OcDropdown.vue.d.ts +19 -0
- package/dist/components/OcDropdownItem.vue.d.ts +18 -0
- package/dist/components/OcDropdownLabel.vue.d.ts +12 -0
- package/dist/components/OcDropdownSeparator.vue.d.ts +2 -0
- package/dist/components/OcDropzone.vue.d.ts +29 -0
- package/dist/components/OcEmojiPicker.vue.d.ts +32 -0
- package/dist/components/OcEmptyState.vue.d.ts +24 -0
- package/dist/components/OcEntityCard.vue.d.ts +37 -0
- package/dist/components/OcFactList.vue.d.ts +29 -0
- package/dist/components/OcFilterCounts.vue.d.ts +25 -0
- package/dist/components/OcFlipCard.vue.d.ts +31 -0
- package/dist/components/OcFormField.vue.d.ts +26 -0
- package/dist/components/OcGreeting.vue.d.ts +26 -0
- package/dist/components/OcHeading.vue.d.ts +24 -0
- package/dist/components/OcHoverCard.vue.d.ts +22 -0
- package/dist/components/OcImageZoom.vue.d.ts +28 -0
- package/dist/components/OcInput.vue.d.ts +13 -0
- package/dist/components/OcInputGroup.vue.d.ts +21 -0
- package/dist/components/OcItem.vue.d.ts +39 -0
- package/dist/components/OcItemGroup.vue.d.ts +12 -0
- package/dist/components/OcItemSeparator.vue.d.ts +2 -0
- package/dist/components/OcKbd.vue.d.ts +12 -0
- package/dist/components/OcKbdGroup.vue.d.ts +17 -0
- package/dist/components/OcLabel.vue.d.ts +19 -0
- package/dist/components/OcLanguageSelect.vue.d.ts +32 -0
- package/dist/components/OcLauncherCard.vue.d.ts +26 -0
- package/dist/components/OcLightbox.vue.d.ts +45 -0
- package/dist/components/OcLinkArrow.vue.d.ts +23 -0
- package/dist/components/OcListToolbar.vue.d.ts +44 -0
- package/dist/components/OcMarquee.vue.d.ts +16 -0
- package/dist/components/OcMediaCard.vue.d.ts +24 -0
- package/dist/components/OcMediaRow.vue.d.ts +21 -0
- package/dist/components/OcMediaThumb.vue.d.ts +32 -0
- package/dist/components/OcMessage.vue.d.ts +63 -0
- package/dist/components/OcMessageList.vue.d.ts +35 -0
- package/dist/components/OcMessageThread.vue.d.ts +80 -0
- package/dist/components/OcModal.vue.d.ts +36 -0
- package/dist/components/OcNavmenu.vue.d.ts +24 -0
- package/dist/components/OcNavmenuList.vue.d.ts +29 -0
- package/dist/components/OcNextTeaser.vue.d.ts +29 -0
- package/dist/components/OcNumberInput.vue.d.ts +25 -0
- package/dist/components/OcOtpInput.vue.d.ts +19 -0
- package/dist/components/OcPageHeader.vue.d.ts +36 -0
- package/dist/components/OcPagination.vue.d.ts +20 -0
- package/dist/components/OcPasswordInput.vue.d.ts +18 -0
- package/dist/components/OcPasswordRequirements.vue.d.ts +19 -0
- package/dist/components/OcPhoneInput.vue.d.ts +25 -0
- package/dist/components/OcPopover.vue.d.ts +24 -0
- package/dist/components/OcPriceCard.vue.d.ts +41 -0
- package/dist/components/OcProductMark.vue.d.ts +25 -0
- package/dist/components/OcProgress.vue.d.ts +11 -0
- package/dist/components/OcProjectCard.vue.d.ts +35 -0
- package/dist/components/OcProse.vue.d.ts +25 -0
- package/dist/components/OcRadio.vue.d.ts +27 -0
- package/dist/components/OcRadioGroup.vue.d.ts +32 -0
- package/dist/components/OcRecoveryCodes.vue.d.ts +36 -0
- package/dist/components/OcScrollArea.vue.d.ts +18 -0
- package/dist/components/OcSegmented.vue.d.ts +21 -0
- package/dist/components/OcSelect.vue.d.ts +28 -0
- package/dist/components/OcSeparator.vue.d.ts +21 -0
- package/dist/components/OcSeverityCard.vue.d.ts +36 -0
- package/dist/components/OcSheet.vue.d.ts +37 -0
- package/dist/components/OcSidebar.vue.d.ts +28 -0
- package/dist/components/OcSidebarCollapsible.vue.d.ts +27 -0
- package/dist/components/OcSidebarGroup.vue.d.ts +16 -0
- package/dist/components/OcSidebarMenu.vue.d.ts +12 -0
- package/dist/components/OcSidebarMenuButton.vue.d.ts +21 -0
- package/dist/components/OcSidebarSeparator.vue.d.ts +2 -0
- package/dist/components/OcSkeleton.vue.d.ts +8 -0
- package/dist/components/OcSlider.vue.d.ts +18 -0
- package/dist/components/OcSortableRow.vue.d.ts +32 -0
- package/dist/components/OcSpinner.vue.d.ts +8 -0
- package/dist/components/OcStackCard.vue.d.ts +22 -0
- package/dist/components/OcStackList.vue.d.ts +28 -0
- package/dist/components/OcStatCard.vue.d.ts +25 -0
- package/dist/components/OcStepper.vue.d.ts +24 -0
- package/dist/components/OcSwitch.vue.d.ts +9 -0
- package/dist/components/OcTable.vue.d.ts +61 -0
- package/dist/components/OcTableActions.vue.d.ts +18 -0
- package/dist/components/OcTableCompact.vue.d.ts +37 -0
- package/dist/components/OcTabs.vue.d.ts +28 -0
- package/dist/components/OcTagInput.vue.d.ts +18 -0
- package/dist/components/OcTerminalLog.vue.d.ts +20 -0
- package/dist/components/OcTextarea.vue.d.ts +13 -0
- package/dist/components/OcThemeSwitch.vue.d.ts +20 -0
- package/dist/components/OcTimeInput.vue.d.ts +14 -0
- package/dist/components/OcTimeline.vue.d.ts +33 -0
- package/dist/components/OcToast.vue.d.ts +31 -0
- package/dist/components/OcToastContainer.vue.d.ts +8 -0
- package/dist/components/OcToggle.vue.d.ts +29 -0
- package/dist/components/OcToggleField.vue.d.ts +27 -0
- package/dist/components/OcToggleGroup.vue.d.ts +27 -0
- package/dist/components/OcTooltip.vue.d.ts +16 -0
- package/dist/components/OcTopProgress.vue.d.ts +18 -0
- package/dist/components/OcTree.vue.d.ts +40 -0
- package/dist/components/OcUpgradeBanner.vue.d.ts +41 -0
- package/dist/components/OcUser.vue.d.ts +20 -0
- package/dist/components/OcVersionBanner.vue.d.ts +32 -0
- package/dist/composables/chartLine.d.ts +6 -0
- package/dist/composables/keys.d.ts +19 -0
- package/dist/composables/useAttrsSplit.d.ts +14 -0
- package/dist/composables/useDialog.d.ts +9 -0
- package/dist/composables/useToast.d.ts +34 -0
- package/dist/composables/useUid.d.ts +5 -0
- package/dist/index.d.ts +233 -0
- package/dist/omniaui-vue.js +8811 -0
- package/dist/omniaui-vue.js.map +1 -0
- package/manifest.json +1036 -0
- package/package.json +67 -4
- package/src/blocks/OcBlockAboutTimeline.vue +44 -0
- package/src/blocks/OcBlockAppHeader.vue +36 -0
- package/src/blocks/OcBlockAppShell.vue +29 -0
- package/src/blocks/OcBlockAuth.vue +24 -0
- package/src/blocks/OcBlockAuthSplit.vue +47 -0
- package/src/blocks/OcBlockContactGrid.vue +53 -0
- package/src/blocks/OcBlockCta.vue +12 -0
- package/src/blocks/OcBlockDataTable.vue +27 -0
- package/src/blocks/OcBlockFaq.vue +49 -0
- package/src/blocks/OcBlockFeatures.vue +23 -0
- package/src/blocks/OcBlockFooter.vue +25 -0
- package/src/blocks/OcBlockFormPage.vue +24 -0
- package/src/blocks/OcBlockHero.vue +13 -0
- package/src/blocks/OcBlockHeroCode.vue +42 -0
- package/src/blocks/OcBlockHeroOrbit.vue +69 -0
- package/src/blocks/OcBlockHeroSplit.vue +15 -0
- package/src/blocks/OcBlockModuleHeader.vue +21 -0
- package/src/blocks/OcBlockPageHero.vue +13 -0
- package/src/blocks/OcBlockPortfolioGrid.vue +63 -0
- package/src/blocks/OcBlockPricing.vue +39 -0
- package/src/blocks/OcBlockProcess.vue +39 -0
- package/src/blocks/OcBlockProductGrid.vue +41 -0
- package/src/blocks/OcBlockProfileHeader.vue +50 -0
- package/src/blocks/OcBlockShowcase.vue +43 -0
- package/src/blocks/OcBlockSiteFooter.vue +54 -0
- package/src/blocks/OcBlockSiteHeader.vue +34 -0
- package/src/blocks/OcBlockSpotlight.vue +47 -0
- package/src/blocks/OcBlockStats.vue +17 -0
- package/src/blocks/OcBlockStatsCounter.vue +20 -0
- package/src/blocks/OcBlockTeamList.vue +53 -0
- package/src/blocks/OcBlockTwoFactor.vue +61 -0
- package/src/blocks/OcBlockWizardDialog.vue +67 -0
- package/src/components/OcAccordion.vue +12 -0
- package/src/components/OcAccordionAccent.vue +27 -0
- package/src/components/OcAccordionItem.vue +19 -0
- package/src/components/OcAffixInput.vue +40 -0
- package/src/components/OcAlert.vue +17 -0
- package/src/components/OcAlertDialog.vue +66 -0
- package/src/components/OcAlphaTabs.vue +54 -0
- package/src/components/OcAspectRatio.vue +21 -0
- package/src/components/OcAttachment.vue +59 -0
- package/src/components/OcAttachmentImage.vue +13 -0
- package/src/components/OcAttachmentList.vue +31 -0
- package/src/components/OcAttachmentThumb.vue +14 -0
- package/src/components/OcAvatar.vue +18 -0
- package/src/components/OcAvatarGroup.vue +7 -0
- package/src/components/OcBackLink.vue +8 -0
- package/src/components/OcBadge.vue +13 -0
- package/src/components/OcBarcodeInput.vue +51 -0
- package/src/components/OcBreadcrumb.vue +22 -0
- package/src/components/OcBrowserFrame.vue +33 -0
- package/src/components/OcBusyOverlay.vue +32 -0
- package/src/components/OcButton.vue +47 -0
- package/src/components/OcButtonGroup.vue +10 -0
- package/src/components/OcButtonGroupText.vue +7 -0
- package/src/components/OcCard.vue +20 -0
- package/src/components/OcChartLine.vue +80 -0
- package/src/components/OcChatComposer.vue +42 -0
- package/src/components/OcCheckbox.vue +26 -0
- package/src/components/OcChecklist.vue +29 -0
- package/src/components/OcChipFilter.vue +48 -0
- package/src/components/OcCollapsible.vue +19 -0
- package/src/components/OcColorField.vue +15 -0
- package/src/components/OcColorSelect.vue +33 -0
- package/src/components/OcColumnMenu.vue +50 -0
- package/src/components/OcCommand.vue +119 -0
- package/src/components/OcConfirmDialog.vue +65 -0
- package/src/components/OcCookieConsent.vue +119 -0
- package/src/components/OcCopyField.vue +37 -0
- package/src/components/OcCounter.vue +15 -0
- package/src/components/OcDataTable.vue +144 -0
- package/src/components/OcDecimalInput.vue +53 -0
- package/src/components/OcDefinitionList.vue +35 -0
- package/src/components/OcDocViewer.vue +79 -0
- package/src/components/OcDropdown.vue +23 -0
- package/src/components/OcDropdownItem.vue +9 -0
- package/src/components/OcDropdownLabel.vue +7 -0
- package/src/components/OcDropdownSeparator.vue +7 -0
- package/src/components/OcDropzone.vue +36 -0
- package/src/components/OcEmojiPicker.vue +45 -0
- package/src/components/OcEmptyState.vue +13 -0
- package/src/components/OcEntityCard.vue +47 -0
- package/src/components/OcFactList.vue +37 -0
- package/src/components/OcFilterCounts.vue +38 -0
- package/src/components/OcFlipCard.vue +36 -0
- package/src/components/OcFormField.vue +36 -0
- package/src/components/OcGreeting.vue +52 -0
- package/src/components/OcHeading.vue +19 -0
- package/src/components/OcHoverCard.vue +25 -0
- package/src/components/OcImageZoom.vue +39 -0
- package/src/components/OcInput.vue +9 -0
- package/src/components/OcInputGroup.vue +12 -0
- package/src/components/OcItem.vue +40 -0
- package/src/components/OcItemGroup.vue +7 -0
- package/src/components/OcItemSeparator.vue +7 -0
- package/src/components/OcKbd.vue +7 -0
- package/src/components/OcKbdGroup.vue +15 -0
- package/src/components/OcLabel.vue +10 -0
- package/src/components/OcLanguageSelect.vue +40 -0
- package/src/components/OcLauncherCard.vue +34 -0
- package/src/components/OcLightbox.vue +63 -0
- package/src/components/OcLinkArrow.vue +25 -0
- package/src/components/OcListToolbar.vue +44 -0
- package/src/components/OcMarquee.vue +36 -0
- package/src/components/OcMediaCard.vue +28 -0
- package/src/components/OcMediaRow.vue +28 -0
- package/src/components/OcMediaThumb.vue +38 -0
- package/src/components/OcMessage.vue +91 -0
- package/src/components/OcMessageList.vue +43 -0
- package/src/components/OcMessageThread.vue +155 -0
- package/src/components/OcModal.vue +42 -0
- package/src/components/OcNavmenu.vue +18 -0
- package/src/components/OcNavmenuList.vue +38 -0
- package/src/components/OcNextTeaser.vue +25 -0
- package/src/components/OcNumberInput.vue +47 -0
- package/src/components/OcOtpInput.vue +34 -0
- package/src/components/OcPageHeader.vue +34 -0
- package/src/components/OcPagination.vue +33 -0
- package/src/components/OcPasswordInput.vue +27 -0
- package/src/components/OcPasswordRequirements.vue +28 -0
- package/src/components/OcPhoneInput.vue +72 -0
- package/src/components/OcPopover.vue +25 -0
- package/src/components/OcPriceCard.vue +69 -0
- package/src/components/OcProductMark.vue +31 -0
- package/src/components/OcProgress.vue +21 -0
- package/src/components/OcProjectCard.vue +36 -0
- package/src/components/OcProse.vue +57 -0
- package/src/components/OcRadio.vue +40 -0
- package/src/components/OcRadioGroup.vue +32 -0
- package/src/components/OcRecoveryCodes.vue +55 -0
- package/src/components/OcScrollArea.vue +15 -0
- package/src/components/OcSegmented.vue +28 -0
- package/src/components/OcSelect.vue +21 -0
- package/src/components/OcSeparator.vue +18 -0
- package/src/components/OcSeverityCard.vue +46 -0
- package/src/components/OcSheet.vue +49 -0
- package/src/components/OcSidebar.vue +16 -0
- package/src/components/OcSidebarCollapsible.vue +19 -0
- package/src/components/OcSidebarGroup.vue +11 -0
- package/src/components/OcSidebarMenu.vue +7 -0
- package/src/components/OcSidebarMenuButton.vue +31 -0
- package/src/components/OcSidebarSeparator.vue +7 -0
- package/src/components/OcSkeleton.vue +8 -0
- package/src/components/OcSlider.vue +27 -0
- package/src/components/OcSortableRow.vue +40 -0
- package/src/components/OcSpinner.vue +13 -0
- package/src/components/OcStackCard.vue +24 -0
- package/src/components/OcStackList.vue +31 -0
- package/src/components/OcStatCard.vue +39 -0
- package/src/components/OcStepper.vue +34 -0
- package/src/components/OcSwitch.vue +15 -0
- package/src/components/OcTable.vue +115 -0
- package/src/components/OcTableActions.vue +26 -0
- package/src/components/OcTableCompact.vue +46 -0
- package/src/components/OcTabs.vue +37 -0
- package/src/components/OcTagInput.vue +50 -0
- package/src/components/OcTerminalLog.vue +50 -0
- package/src/components/OcTextarea.vue +9 -0
- package/src/components/OcThemeSwitch.vue +31 -0
- package/src/components/OcTimeInput.vue +50 -0
- package/src/components/OcTimeline.vue +36 -0
- package/src/components/OcToast.vue +31 -0
- package/src/components/OcToastContainer.vue +21 -0
- package/src/components/OcToggle.vue +63 -0
- package/src/components/OcToggleField.vue +28 -0
- package/src/components/OcToggleGroup.vue +40 -0
- package/src/components/OcTooltip.vue +8 -0
- package/src/components/OcTopProgress.vue +54 -0
- package/src/components/OcTree.vue +70 -0
- package/src/components/OcUpgradeBanner.vue +42 -0
- package/src/components/OcUser.vue +25 -0
- package/src/components/OcVersionBanner.vue +34 -0
- package/src/composables/chartLine.ts +28 -0
- package/src/composables/keys.ts +22 -0
- package/src/composables/useAttrsSplit.ts +16 -0
- package/src/composables/useDialog.ts +21 -0
- package/src/composables/useToast.ts +66 -0
- package/src/composables/useUid.ts +12 -0
- package/src/index.ts +589 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Warning panel with a code grid plus "copy all" and "download .txt" actions (handled here).
|
|
4
|
+
* Emits `copy` and `download`. Slot: actions (replaces the two buttons).
|
|
5
|
+
*/
|
|
6
|
+
const props = withDefaults(
|
|
7
|
+
defineProps<{
|
|
8
|
+
codes: string[]
|
|
9
|
+
title?: string
|
|
10
|
+
warning?: string
|
|
11
|
+
copyLabel?: string
|
|
12
|
+
downloadLabel?: string
|
|
13
|
+
filename?: string
|
|
14
|
+
}>(),
|
|
15
|
+
{
|
|
16
|
+
title: 'Recovery codes',
|
|
17
|
+
warning: 'Store these codes somewhere safe. Each code works once.',
|
|
18
|
+
copyLabel: 'Copy all',
|
|
19
|
+
downloadLabel: 'Download .txt',
|
|
20
|
+
filename: 'recovery-codes.txt',
|
|
21
|
+
},
|
|
22
|
+
)
|
|
23
|
+
const emit = defineEmits<{ copy: []; download: [] }>()
|
|
24
|
+
|
|
25
|
+
async function copyAll() {
|
|
26
|
+
await navigator.clipboard.writeText(props.codes.join('\n'))
|
|
27
|
+
emit('copy')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function download() {
|
|
31
|
+
const url = URL.createObjectURL(new Blob([props.codes.join('\n') + '\n'], { type: 'text/plain' }))
|
|
32
|
+
const a = document.createElement('a')
|
|
33
|
+
a.href = url
|
|
34
|
+
a.download = props.filename
|
|
35
|
+
a.click()
|
|
36
|
+
URL.revokeObjectURL(url)
|
|
37
|
+
emit('download')
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<div class="oc-recovery-codes">
|
|
43
|
+
<h3 class="oc-recovery-codes-title">{{ title }}</h3>
|
|
44
|
+
<p class="oc-recovery-codes-warning">{{ warning }}</p>
|
|
45
|
+
<ul class="oc-recovery-codes-list">
|
|
46
|
+
<li v-for="code in codes" :key="code">{{ code }}</li>
|
|
47
|
+
</ul>
|
|
48
|
+
<div class="oc-recovery-codes-actions">
|
|
49
|
+
<slot name="actions">
|
|
50
|
+
<button class="oc-btn oc-btn--outline oc-btn--sm" type="button" @click="copyAll">{{ copyLabel }}</button>
|
|
51
|
+
<button class="oc-btn oc-btn--outline oc-btn--sm" type="button" @click="download">{{ downloadLabel }}</button>
|
|
52
|
+
</slot>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Bounded scroll region (focusable, role=region) with themed scrollbar. `label` = aria-label. Classes: .oc-scroll-area(--x/--shadows) */
|
|
3
|
+
defineProps<{ horizontal?: boolean; shadows?: boolean; label?: string }>()
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<div
|
|
8
|
+
:class="['oc-scroll-area', horizontal && 'oc-scroll-area--x', shadows && 'oc-scroll-area--shadows']"
|
|
9
|
+
tabindex="0"
|
|
10
|
+
role="region"
|
|
11
|
+
:aria-label="label"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Radio group as a pill switcher. v-model = selected value. Classes: .oc-segmented(--block/--sm), -item */
|
|
3
|
+
import { useUid } from '../composables/useUid'
|
|
4
|
+
|
|
5
|
+
export interface SegmentedOption {
|
|
6
|
+
value: string
|
|
7
|
+
label: string
|
|
8
|
+
}
|
|
9
|
+
defineProps<{
|
|
10
|
+
options: SegmentedOption[]
|
|
11
|
+
/** aria-label of the group */
|
|
12
|
+
label?: string
|
|
13
|
+
block?: boolean
|
|
14
|
+
size?: 'sm' | 'md'
|
|
15
|
+
name?: string
|
|
16
|
+
}>()
|
|
17
|
+
const model = defineModel<string>()
|
|
18
|
+
const uid = useUid('oc-segmented')
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<template>
|
|
22
|
+
<div :class="['oc-segmented', block && 'oc-segmented--block', size === 'sm' && 'oc-segmented--sm']" role="radiogroup" :aria-label="label">
|
|
23
|
+
<label v-for="option in options" :key="option.value" class="oc-segmented-item">
|
|
24
|
+
<input v-model="model" type="radio" :name="name ?? uid" :value="option.value" />
|
|
25
|
+
{{ option.label }}
|
|
26
|
+
</label>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Native select. v-model. Pass `options` (strings or { value, label }) or <option> elements in the default slot. */
|
|
3
|
+
export interface SelectOption {
|
|
4
|
+
value: string | number
|
|
5
|
+
label: string
|
|
6
|
+
disabled?: boolean
|
|
7
|
+
}
|
|
8
|
+
defineProps<{ options?: (string | SelectOption)[] }>()
|
|
9
|
+
const model = defineModel<any>()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<select v-model="model" class="oc-select">
|
|
14
|
+
<slot>
|
|
15
|
+
<template v-for="o in options" :key="typeof o === 'string' ? o : o.value">
|
|
16
|
+
<option v-if="typeof o === 'string'" :value="o">{{ o }}</option>
|
|
17
|
+
<option v-else :value="o.value" :disabled="o.disabled">{{ o.label }}</option>
|
|
18
|
+
</template>
|
|
19
|
+
</slot>
|
|
20
|
+
</select>
|
|
21
|
+
</template>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Divider. Default = <hr>. `vertical` = inline separator for flex rows. `label` (or the default slot) renders the
|
|
4
|
+
* line-text-line form. Classes: .oc-separator(--vertical/--strong), .oc-separator-text
|
|
5
|
+
*/
|
|
6
|
+
defineProps<{ vertical?: boolean; strong?: boolean; label?: string }>()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<div v-if="label || $slots.default" class="oc-separator-text" role="separator"><span><slot>{{ label }}</slot></span></div>
|
|
11
|
+
<span
|
|
12
|
+
v-else-if="vertical"
|
|
13
|
+
:class="['oc-separator', 'oc-separator--vertical', strong && 'oc-separator--strong']"
|
|
14
|
+
role="separator"
|
|
15
|
+
aria-orientation="vertical"
|
|
16
|
+
></span>
|
|
17
|
+
<hr v-else :class="['oc-separator', strong && 'oc-separator--strong']" />
|
|
18
|
+
</template>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!-- File: packages/vue/src/components/OcSeverityCard.vue | Map: details -> summary head (icon, title + tags, level badge) -> body (default slot, actions slot) -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
/**
|
|
4
|
+
* Expandable card colored by risk level. v-model:open. Cards with the same `name` open one at a time.
|
|
5
|
+
* Slots: icon, default (body), actions.
|
|
6
|
+
* Classes: details.oc-severity-card(--low/--medium/--high/--critical, .is-resolved), -head, -icon, -main, -title, -tags, -tag, -level, -body, -actions
|
|
7
|
+
*/
|
|
8
|
+
const props = defineProps<{
|
|
9
|
+
level: 'low' | 'medium' | 'high' | 'critical'
|
|
10
|
+
title: string
|
|
11
|
+
tags?: string[]
|
|
12
|
+
levelLabel?: string
|
|
13
|
+
resolved?: boolean
|
|
14
|
+
name?: string
|
|
15
|
+
}>()
|
|
16
|
+
const open = defineModel<boolean>('open', { default: false })
|
|
17
|
+
const LEVEL_TEXT = { low: 'Low', medium: 'Medium', high: 'High', critical: 'Critical' } as const
|
|
18
|
+
|
|
19
|
+
function onToggle(e: Event) {
|
|
20
|
+
open.value = (e.target as HTMLDetailsElement).open
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<details
|
|
26
|
+
:class="['oc-severity-card', `oc-severity-card--${level}`, resolved && 'is-resolved']"
|
|
27
|
+
:name="name"
|
|
28
|
+
:open="open"
|
|
29
|
+
@toggle="onToggle"
|
|
30
|
+
>
|
|
31
|
+
<summary class="oc-severity-card-head">
|
|
32
|
+
<span v-if="$slots.icon" class="oc-severity-card-icon" aria-hidden="true"><slot name="icon" /></span>
|
|
33
|
+
<span class="oc-severity-card-main">
|
|
34
|
+
<span class="oc-severity-card-title">{{ title }}</span>
|
|
35
|
+
<span v-if="tags?.length" class="oc-severity-card-tags">
|
|
36
|
+
<span v-for="t in tags" :key="t" class="oc-severity-card-tag">{{ t }}</span>
|
|
37
|
+
</span>
|
|
38
|
+
</span>
|
|
39
|
+
<span class="oc-severity-card-level">{{ levelLabel ?? LEVEL_TEXT[props.level] }}</span>
|
|
40
|
+
</summary>
|
|
41
|
+
<div class="oc-severity-card-body">
|
|
42
|
+
<slot />
|
|
43
|
+
<div v-if="$slots.actions" class="oc-severity-card-actions"><slot name="actions" /></div>
|
|
44
|
+
</div>
|
|
45
|
+
</details>
|
|
46
|
+
</template>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Side panel on a native <dialog>. v-model:open. Slots: header (replaces title + description),
|
|
4
|
+
* default (body), footer (scoped: { close }). Classes: dialog.oc-sheet(--left/--top/--bottom),
|
|
5
|
+
* .oc-sheet-content(--wide), -header, -title, -description, -body, -footer, -close.
|
|
6
|
+
*/
|
|
7
|
+
import { ref } from 'vue'
|
|
8
|
+
import { useDialog } from '../composables/useDialog'
|
|
9
|
+
import { useUid } from '../composables/useUid'
|
|
10
|
+
|
|
11
|
+
withDefaults(
|
|
12
|
+
defineProps<{
|
|
13
|
+
side?: 'right' | 'left' | 'top' | 'bottom'
|
|
14
|
+
wide?: boolean
|
|
15
|
+
title?: string
|
|
16
|
+
description?: string
|
|
17
|
+
closeLabel?: string
|
|
18
|
+
}>(),
|
|
19
|
+
{ side: 'right', closeLabel: 'Close' },
|
|
20
|
+
)
|
|
21
|
+
const open = defineModel<boolean>('open', { default: false })
|
|
22
|
+
const el = ref<HTMLDialogElement | null>(null)
|
|
23
|
+
const { onClose } = useDialog(open, el)
|
|
24
|
+
const titleId = useUid('oc-sheet-title')
|
|
25
|
+
const close = () => (open.value = false)
|
|
26
|
+
defineExpose({ close })
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<dialog
|
|
31
|
+
ref="el"
|
|
32
|
+
:class="['oc-sheet', side !== 'right' && `oc-sheet--${side}`]"
|
|
33
|
+
closedby="any"
|
|
34
|
+
:aria-labelledby="title ? titleId : undefined"
|
|
35
|
+
@close="onClose"
|
|
36
|
+
>
|
|
37
|
+
<div :class="['oc-sheet-content', wide && 'oc-sheet-content--wide']">
|
|
38
|
+
<button class="oc-sheet-close" type="button" :aria-label="closeLabel" @click="close">×</button>
|
|
39
|
+
<div v-if="title || description || $slots.header" class="oc-sheet-header">
|
|
40
|
+
<slot name="header">
|
|
41
|
+
<h2 v-if="title" :id="titleId" class="oc-sheet-title">{{ title }}</h2>
|
|
42
|
+
<p v-if="description" class="oc-sheet-description">{{ description }}</p>
|
|
43
|
+
</slot>
|
|
44
|
+
</div>
|
|
45
|
+
<div v-if="$slots.default" class="oc-sheet-body"><slot /></div>
|
|
46
|
+
<div v-if="$slots.footer" class="oc-sheet-footer"><slot name="footer" :close="close" /></div>
|
|
47
|
+
</div>
|
|
48
|
+
</dialog>
|
|
49
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Vertical navigation shell. Slots: header, default (scrolling content: OcSidebarGroup...), footer.
|
|
4
|
+
* Classes: .oc-sidebar(--collapsed/--right/--floating/--dark), -header, -content, -footer.
|
|
5
|
+
* Compose with OcSidebarGroup, OcSidebarMenu, OcSidebarMenuButton, OcSidebarCollapsible, OcSidebarSeparator.
|
|
6
|
+
*/
|
|
7
|
+
defineProps<{ collapsed?: boolean; right?: boolean; floating?: boolean; dark?: boolean; label?: string }>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<aside :class="['oc-sidebar', collapsed && 'oc-sidebar--collapsed', right && 'oc-sidebar--right', floating && 'oc-sidebar--floating', dark && 'oc-sidebar--dark']" :aria-label="label">
|
|
12
|
+
<div v-if="$slots.header" class="oc-sidebar-header"><slot name="header" /></div>
|
|
13
|
+
<div class="oc-sidebar-content"><slot /></div>
|
|
14
|
+
<div v-if="$slots.footer" class="oc-sidebar-footer"><slot name="footer" /></div>
|
|
15
|
+
</aside>
|
|
16
|
+
</template>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Expandable sidebar item (details). v-model:open. Slots: icon, label (or `label` prop), default (sub items as <li>). */
|
|
3
|
+
defineProps<{ label?: string }>()
|
|
4
|
+
const open = defineModel<boolean>('open', { default: false })
|
|
5
|
+
|
|
6
|
+
function onToggle(e: Event) {
|
|
7
|
+
open.value = (e.target as HTMLDetailsElement).open
|
|
8
|
+
}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<details class="oc-sidebar-collapsible" :open="open" @toggle="onToggle">
|
|
13
|
+
<summary class="oc-sidebar-menu-button">
|
|
14
|
+
<slot name="icon" />
|
|
15
|
+
<span class="oc-sidebar-menu-label"><slot name="label">{{ label }}</slot></span>
|
|
16
|
+
</summary>
|
|
17
|
+
<ul class="oc-sidebar-menu-sub"><slot /></ul>
|
|
18
|
+
</details>
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/** Group of sidebar items with an optional heading (`label`). */
|
|
3
|
+
defineProps<{ label?: string }>()
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<template>
|
|
7
|
+
<div class="oc-sidebar-group">
|
|
8
|
+
<div v-if="label" class="oc-sidebar-group-label">{{ label }}</div>
|
|
9
|
+
<slot />
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|
|
@@ -0,0 +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>
|