@livestorm/ui-vue 3.0.0 → 4.0.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/README.md +3 -3
- package/components-vite.js +2 -2
- package/dist/UiButton-uyW8EHRJ.mjs +602 -0
- package/dist/UiTimelineItem-EiOEi1yF.mjs +7293 -0
- package/dist/UiTooltip-DZcPD6_N.mjs +158 -0
- package/dist/a11y-CaZxRWzo.mjs +6 -0
- package/dist/breakpoints.mjs +4 -9
- package/dist/bus.mjs +5 -5
- package/dist/components.mjs +236 -231
- package/dist/i18n-B8QOMuFD.mjs +46 -0
- package/dist/index.mjs +4 -91
- package/dist/integrations.mjs +3 -14
- package/dist/layouts.mjs +228 -236
- package/dist/responsive.mjs +31 -36
- package/dist/slot.mjs +11 -17
- package/dist/toastDSV2-D3xDZPe5.mjs +105 -0
- package/dist/types/index.d.ts +19 -1
- package/dist/types/src/components/Toast/ToastMessage.vue.d.ts +17 -7
- package/dist/types/src/components/Toast/toastDSV2.d.ts +89 -64
- package/dist/types/src/components/UiActionBar/types.d.ts +2 -0
- package/dist/types/src/components/UiAvatar/UiAvatar.vue.d.ts +4 -2
- package/dist/types/src/components/UiAvatarList/UiAvatarList.vue.d.ts +3 -2
- package/dist/types/src/components/UiBanner/UiBanner.vue.d.ts +13 -1
- package/dist/types/src/components/UiButton/UiButton.vue.d.ts +95 -35
- package/dist/types/src/components/UiButtonGroup/UiButtonGroup.vue.d.ts +8 -2
- package/dist/types/src/components/UiButtonGroup/types.d.ts +4 -0
- package/dist/types/src/components/UiChoice/UiChoice.vue.d.ts +71 -0
- package/dist/types/src/components/UiChoice/index.d.ts +2 -0
- package/dist/types/src/components/UiChoice/types.d.ts +7 -0
- package/dist/types/src/components/UiColorField/UiColorField.vue.d.ts +1 -1
- package/dist/types/src/components/UiColorPicker/UiColorPicker.vue.d.ts +2 -2
- package/dist/types/src/components/UiCombobox/UiCombobox.types.d.ts +47 -0
- package/dist/types/src/components/UiCombobox/UiCombobox.vue.d.ts +40 -0
- package/dist/types/src/components/UiCombobox/index.d.ts +2 -0
- package/dist/types/src/components/UiDataTable/UiDataTable.types.d.ts +46 -0
- package/dist/types/src/components/UiDataTable/UiDataTable.vue.d.ts +136 -0
- package/dist/types/src/components/UiDataTable/index.d.ts +5 -0
- package/dist/types/src/components/UiDrawer/UiDrawer.vue.d.ts +28 -0
- package/dist/types/src/components/UiDrawer/UiDrawerContent.vue.d.ts +18 -0
- package/dist/types/src/components/UiDrawer/UiDrawerTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiDropdown/DropdownItemCheckbox.vue.d.ts +3 -0
- package/dist/types/src/components/UiDropdown/UiDropdownContent.vue.d.ts +10 -0
- package/dist/types/src/components/UiDropdown/UiDropdownGroup.vue.d.ts +17 -0
- package/dist/types/src/components/UiDropdown/UiDropdownItem.vue.d.ts +8 -5
- package/dist/types/src/components/UiDropdown/UiDropdownTrigger.vue.d.ts +21 -5
- package/dist/types/src/components/UiDropdown/index.d.ts +1 -0
- package/dist/types/src/components/UiEmojiPickerList/UiEmojiPickerList.vue.d.ts +22 -0
- package/dist/types/src/components/UiEmptyState/UiEmptyState.vue.d.ts +8 -3
- package/dist/types/src/components/UiFieldWrapper/UiFieldWrapper.vue.d.ts +2 -2
- package/dist/types/src/components/UiInputCheckbox/CheckboxGlyph.vue.d.ts +17 -0
- package/dist/types/src/components/UiInputCheckbox/UiInputCheckbox.vue.d.ts +35 -4
- package/dist/types/src/components/UiInputRadio/RadioGlyph.vue.d.ts +19 -0
- package/dist/types/src/components/UiInputRadio/UiInputRadio.vue.d.ts +21 -8
- package/dist/types/src/components/UiInputRadio/UiInputRadioGroup.vue.d.ts +6 -1
- package/dist/types/src/components/UiInputRadio/types.d.ts +1 -1
- package/dist/types/src/components/UiInputSelect/UiInputSelect.vue.d.ts +5 -5
- package/dist/types/src/components/UiInputTextarea/UiInputTextarea.vue.d.ts +5 -5
- package/dist/types/src/components/UiListItem/UiListItem.vue.d.ts +18 -4
- package/dist/types/src/components/UiLoader/UiSpinnerIcon.vue.d.ts +3 -0
- package/dist/types/src/components/UiMenu/UiMenuContent.vue.d.ts +15 -2
- package/dist/types/src/components/UiMenu/UiMenuItem.vue.d.ts +9 -3
- package/dist/types/src/components/UiNestedOptions/UiNestedOptions.vue.d.ts +13 -0
- package/dist/types/src/components/UiPage/UiPage.vue.d.ts +79 -15
- package/dist/types/src/components/UiPagination/UiPagination.vue.d.ts +36 -0
- package/dist/types/src/components/UiPagination/index.d.ts +2 -0
- package/dist/types/src/components/UiPagination/types.d.ts +4 -0
- package/dist/types/src/components/UiPane/UiPane.vue.d.ts +22 -0
- package/dist/types/src/components/UiPane/UiPaneContent.vue.d.ts +75 -0
- package/dist/types/src/components/UiPane/UiPaneTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiPane/index.d.ts +5 -0
- package/dist/types/src/components/UiRating/UiRating.vue.d.ts +62 -0
- package/dist/types/src/components/UiRating/types.d.ts +1 -0
- package/dist/types/src/components/UiRoomButton/UiRoomButton.vue.d.ts +5 -3
- package/dist/types/src/components/UiRoomCountdown/UiRoomCountdown.vue.d.ts +32 -0
- package/dist/types/src/components/UiShell/UiShell.vue.d.ts +3 -0
- package/dist/types/src/components/UiSideMenu/UiSideMenu.vue.d.ts +22 -1
- package/dist/types/src/components/UiSideMenu/UiSideMenuItemContent.vue.d.ts +2 -2
- package/dist/types/src/components/UiSwitch/UiSwitch.vue.d.ts +10 -5
- package/dist/types/src/components/UiTable/UiTable.vue.d.ts +13 -4
- package/dist/types/src/components/UiTable/UiTableActionsCell.vue.d.ts +49 -0
- package/dist/types/src/components/UiTable/UiTableActionsHeaderCell.vue.d.ts +3 -0
- package/dist/types/src/components/UiTable/UiTableBody.vue.d.ts +11 -1
- package/dist/types/src/components/UiTable/UiTableCell.vue.d.ts +16 -1
- package/dist/types/src/components/UiTable/UiTableHeaderCell.vue.d.ts +31 -2
- package/dist/types/src/components/UiTable/UiTableRow.vue.d.ts +32 -2
- package/dist/types/src/components/UiTable/context.d.ts +3 -0
- package/dist/types/src/components/UiTable/index.d.ts +4 -0
- package/dist/types/src/components/UiTabs/UiTabs.vue.d.ts +3 -0
- package/dist/types/src/components/UiTag/UiTag.types.d.ts +25 -0
- package/dist/types/src/components/UiTag/UiTag.vue.d.ts +5 -26
- package/dist/types/src/components/UiTag/index.d.ts +2 -1
- package/dist/types/src/components/UiTextField/UiTextField.vue.d.ts +10 -5
- package/dist/types/src/components/UiTooltip/UiTooltipProvider.vue.d.ts +1 -0
- package/dist/types/src/components/UiTooltip/UiTooltipTrigger.vue.d.ts +2 -2
- package/dist/types/src/composables/storedThemingApplies.d.ts +17 -0
- package/dist/types/src/composables/useButtonStyles.d.ts +1 -0
- package/dist/types/src/composables/useChoiceboxSurface.d.ts +11 -0
- package/dist/types/src/composables/useContentMode.d.ts +7 -9
- package/dist/types/src/composables/useControlModes.d.ts +7 -0
- package/dist/types/src/composables/useControlShape.d.ts +24 -0
- package/dist/types/src/composables/useFieldFocusEvents.d.ts +12 -0
- package/dist/types/src/composables/useIconSize.d.ts +2 -0
- package/dist/types/src/composables/usePullGesture.d.ts +42 -0
- package/dist/types/src/composables/useThemeAndModes.d.ts +4 -0
- package/dist/types/src/theming/colorScale.d.ts +165 -0
- package/dist/types/src/theming/legacyColorScale.d.ts +27 -0
- package/dist/types/src/theming/presetColors.d.ts +11 -0
- package/dist/types/src/theming/primitiveTokens.d.ts +2 -0
- package/dist/types/src/utils/effectiveOpacity.d.ts +2 -0
- package/dist/types/src/utils/numbers.d.ts +1 -2
- package/dist/types/src/utils/tokenColor.d.ts +2 -0
- package/dist/ui-vue.css +2 -1
- package/dist/utils.mjs +165 -194
- package/index.d.ts +18 -0
- package/index.js +36 -0
- package/package.json +26 -21
- package/src/components/Toast/LayoutToasts.vue +19 -11
- package/src/components/Toast/ToastMessage.vue +125 -68
- package/src/components/Toast/toastDSV2.ts +238 -67
- package/src/components/UiActionBar/UiActionBar.vue +4 -3
- package/src/components/UiActionBar/UiActionBarItem.vue +9 -6
- package/src/components/UiActionBar/types.ts +13 -0
- package/src/components/UiAvatar/UiAvatar.vue +8 -2
- package/src/components/UiAvatarList/UiAvatarList.vue +51 -20
- package/src/components/UiBadge/UiBadge.vue +1 -1
- package/src/components/UiBanner/UiBanner.vue +71 -21
- package/src/components/UiBreadcrumb/UiBreadcrumb.vue +1 -1
- package/src/components/UiButton/UiButton.vue +92 -25
- package/src/components/UiButtonGroup/UiButtonGroup.vue +21 -17
- package/src/components/UiButtonGroup/UiButtonGroupItem.vue +33 -15
- package/src/components/UiButtonGroup/types.ts +19 -0
- package/src/components/UiCard/UiCard.vue +20 -23
- package/src/components/UiChoice/UiChoice.vue +187 -0
- package/src/components/UiChoice/index.ts +2 -0
- package/src/components/UiChoice/types.ts +11 -0
- package/src/components/UiColorField/UiColorField.vue +2 -2
- package/src/components/UiColorPicker/UiColorPicker.vue +11 -8
- package/src/components/UiCombobox/UiCombobox.types.ts +52 -0
- package/src/components/UiCombobox/UiCombobox.vue +296 -0
- package/src/components/UiCombobox/index.ts +2 -0
- package/src/components/UiDataTable/UiDataTable.types.ts +47 -0
- package/src/components/UiDataTable/UiDataTable.vue +422 -0
- package/src/components/UiDataTable/index.ts +12 -0
- package/src/components/UiDialog/UiDialogContent.vue +22 -7
- package/src/components/UiDrawer/UiDrawer.vue +16 -0
- package/src/components/UiDrawer/UiDrawerContent.vue +42 -0
- package/src/components/UiDrawer/UiDrawerTrigger.vue +17 -0
- package/src/components/UiDropdown/DropdownItemCheckbox.vue +10 -0
- package/src/components/UiDropdown/UiDropdownContent.vue +32 -21
- package/src/components/UiDropdown/UiDropdownGroup.vue +23 -0
- package/src/components/UiDropdown/UiDropdownItem.vue +38 -18
- package/src/components/UiDropdown/UiDropdownSeparator.vue +1 -1
- package/src/components/UiDropdown/UiDropdownTrigger.vue +138 -43
- package/src/components/UiDropdown/index.ts +1 -0
- package/src/components/UiEmojiPickerList/UiEmojiPickerList.vue +122 -0
- package/src/components/UiEmptyState/UiEmptyState.vue +16 -4
- package/src/components/UiFieldWrapper/UiFieldWrapper.vue +9 -3
- package/src/components/UiHorizontalSeparator/UiHorizontalSeparator.vue +2 -2
- package/src/components/UiInputCheckbox/CheckboxGlyph.vue +78 -0
- package/src/components/UiInputCheckbox/UiInputCheckbox.vue +213 -177
- package/src/components/UiInputEmoji/UiInputEmoji.vue +18 -95
- package/src/components/UiInputRadio/RadioGlyph.vue +45 -0
- package/src/components/UiInputRadio/UiInputRadio.vue +177 -169
- package/src/components/UiInputRadio/UiInputRadioGroup.vue +15 -5
- package/src/components/UiInputRadio/types.ts +1 -2
- package/src/components/UiInputSelect/UiInputSelect.vue +9 -7
- package/src/components/UiInputTextarea/UiInputTextarea.vue +20 -35
- package/src/components/UiLabel/UiLabel.vue +1 -1
- package/src/components/UiListItem/UiListItem.vue +55 -9
- package/src/components/UiLoader/UiLoader.vue +4 -20
- package/src/components/UiLoader/UiSpinnerIcon.vue +21 -0
- package/src/components/UiMenu/UiMenuContent.vue +24 -3
- package/src/components/UiMenu/UiMenuGroup.vue +1 -1
- package/src/components/UiMenu/UiMenuItem.vue +14 -3
- package/src/components/UiMenu/UiMenuSubContent.vue +1 -1
- package/src/components/UiMenu/UiMenuSubTrigger.vue +1 -1
- package/src/components/UiNestedOptions/UiNestedOptions.vue +6 -0
- package/src/components/UiPage/UiPage.vue +190 -32
- package/src/components/UiPagination/UiPagination.vue +99 -0
- package/src/components/UiPagination/index.ts +2 -0
- package/src/components/UiPagination/types.ts +28 -0
- package/src/components/UiPane/UiPane.vue +20 -0
- package/src/components/UiPane/UiPaneContent.vue +232 -0
- package/src/components/UiPane/UiPaneTrigger.vue +14 -0
- package/src/components/UiPane/index.ts +12 -0
- package/src/components/UiPopover/UiPopoverContent.vue +21 -1
- package/src/components/UiProgress/UiProgress.vue +2 -2
- package/src/components/UiRating/UiRating.vue +258 -0
- package/src/components/UiRating/types.ts +1 -0
- package/src/components/UiRoomButton/UiRoomButton.vue +10 -41
- package/src/components/UiRoomCountdown/UiRoomCountdown.vue +376 -0
- package/src/components/UiShell/UiShell.vue +9 -3
- package/src/components/UiSideMenu/UiSideMenu.vue +155 -18
- package/src/components/UiSideMenu/UiSideMenuItemContent.vue +20 -16
- package/src/components/UiStepper/UiStepper.vue +3 -16
- package/src/components/UiStepper/UiStepperDescription.vue +1 -13
- package/src/components/UiStepper/UiStepperIndicator.vue +11 -48
- package/src/components/UiStepper/UiStepperItem.vue +1 -8
- package/src/components/UiStepper/UiStepperSeparator.vue +5 -16
- package/src/components/UiStepper/UiStepperTitle.vue +1 -10
- package/src/components/UiSwitch/UiSwitch.vue +44 -28
- package/src/components/UiTable/UiTable.vue +98 -8
- package/src/components/UiTable/UiTableActionsCell.vue +135 -0
- package/src/components/UiTable/UiTableActionsHeaderCell.vue +19 -0
- package/src/components/UiTable/UiTableBody.vue +16 -1
- package/src/components/UiTable/UiTableCell.vue +33 -16
- package/src/components/UiTable/UiTableHeader.vue +6 -5
- package/src/components/UiTable/UiTableHeaderCell.vue +61 -9
- package/src/components/UiTable/UiTableRow.vue +46 -10
- package/src/components/UiTable/context.ts +5 -0
- package/src/components/UiTable/index.ts +4 -0
- package/src/components/UiTabs/UiTabs.vue +56 -61
- package/src/components/UiTag/UiTag.types.ts +28 -0
- package/src/components/UiTag/UiTag.vue +24 -42
- package/src/components/UiTag/index.ts +2 -0
- package/src/components/UiTextField/UiTextField.vue +21 -36
- package/src/components/UiTooltip/UiTooltipContent.vue +1 -1
- package/src/components/UiTooltip/UiTooltipProvider.vue +3 -0
- package/src/components/UiTooltip/UiTooltipTrigger.vue +16 -1
- package/src/composables/storedThemingApplies.ts +19 -0
- package/src/composables/useButtonStyles.ts +9 -13
- package/src/composables/useChoiceboxSurface.ts +36 -0
- package/src/composables/useContentMode.ts +29 -16
- package/src/composables/useControlModes.ts +11 -0
- package/src/composables/useControlShape.ts +34 -0
- package/src/composables/useFieldFocusEvents.ts +30 -0
- package/src/composables/useIconSize.ts +15 -0
- package/src/composables/usePullGesture.ts +142 -0
- package/src/composables/useThemeAndModes.ts +28 -1
- package/src/css/body.css +16 -1
- package/src/css/fonts.css +39 -5
- package/src/global.d.ts +36 -0
- package/src/theming/colorScale.ts +173 -0
- package/src/theming/legacyColorScale.ts +58 -0
- package/src/theming/presetColors.ts +33 -0
- package/src/theming/primitiveTokens.ts +71 -0
- package/src/utils/effectiveOpacity.ts +8 -0
- package/src/utils/i18n.ts +6 -0
- package/src/utils/numbers.ts +1 -1
- package/src/utils/responsive.d.ts +14 -0
- package/src/utils/tokenColor.ts +9 -0
- package/dist/UiTimelineItem.vue_vue_type_style_index_0_lang-LpdvGf5X.mjs +0 -6093
- package/dist/a11y-BhF_nl7L.mjs +0 -159
- package/dist/i18n-Cktw9hIu.mjs +0 -49
- package/dist/toastDSV2-wMh-UMzW.mjs +0 -74
- package/dist/types/src/components/UiAvatar/index.d.ts +0 -1
- package/dist/types/src/components/UiAvatarList/index.d.ts +0 -1
- package/dist/types/src/components/UiBadge/index.d.ts +0 -1
- package/dist/types/src/components/UiBanner/index.d.ts +0 -2
- package/dist/types/src/components/UiButtonGroup/index.d.ts +0 -3
- package/dist/types/src/components/UiCarousel/index.d.ts +0 -2
- package/dist/types/src/components/UiColorField/index.d.ts +0 -2
- package/dist/types/src/components/UiDialog/MarketplaceHeaderExample.vue.d.ts +0 -28
- package/dist/types/src/components/UiDialog/index.d.ts +0 -7
- package/dist/types/src/components/UiFieldWrapper/index.d.ts +0 -1
- package/dist/types/src/components/UiInputCheckbox/index.d.ts +0 -2
- package/dist/types/src/components/UiInputEmoji/index.d.ts +0 -1
- package/dist/types/src/components/UiInputRadio/index.d.ts +0 -3
- package/dist/types/src/components/UiInputSelect/index.d.ts +0 -2
- package/dist/types/src/components/UiInputTextarea/index.d.ts +0 -2
- package/dist/types/src/components/UiMenu/index.d.ts +0 -10
- package/dist/types/src/components/UiProgress/index.d.ts +0 -2
- package/dist/types/src/components/UiSwitch/index.d.ts +0 -2
- package/dist/types/src/components/UiTabs/index.d.ts +0 -2
- package/dist/types/src/components/UiTimeline/index.d.ts +0 -2
- package/dist/types/src/components/UiTooltip/index.d.ts +0 -4
- package/dist/types/src/mixins/DynamicAction.d.ts +0 -30
- package/dist/useThemeAndModes-BzYwSOEv.mjs +0 -108
- package/src/components/UiAvatar/index.js +0 -1
- package/src/components/UiAvatarList/index.js +0 -1
- package/src/components/UiBadge/index.ts +0 -2
- package/src/components/UiBanner/index.ts +0 -2
- package/src/components/UiButtonGroup/index.ts +0 -3
- package/src/components/UiCarousel/index.ts +0 -2
- package/src/components/UiColorField/index.ts +0 -2
- package/src/components/UiDialog/MarketplaceHeaderExample.vue +0 -217
- package/src/components/UiDialog/index.ts +0 -18
- package/src/components/UiFieldWrapper/index.ts +0 -1
- package/src/components/UiInputCheckbox/index.ts +0 -2
- package/src/components/UiInputEmoji/index.ts +0 -1
- package/src/components/UiInputRadio/index.ts +0 -3
- package/src/components/UiInputSelect/index.ts +0 -2
- package/src/components/UiInputTextarea/index.ts +0 -2
- package/src/components/UiMenu/index.ts +0 -10
- package/src/components/UiProgress/index.ts +0 -2
- package/src/components/UiSwitch/index.ts +0 -2
- package/src/components/UiTabs/index.ts +0 -5
- package/src/components/UiTag/index.js +0 -1
- package/src/components/UiTimeline/index.ts +0 -2
- package/src/components/UiTooltip/index.js +0 -4
- package/src/mixins/DynamicAction.js +0 -61
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ui-room-countdown">
|
|
3
|
+
<div
|
|
4
|
+
class="ui-room-countdown__dial"
|
|
5
|
+
:style="{ '--ui-room-countdown-size': sizeValue }"
|
|
6
|
+
role="timer"
|
|
7
|
+
aria-live="assertive"
|
|
8
|
+
:aria-label="isFinished ? label : `${remaining}`"
|
|
9
|
+
>
|
|
10
|
+
<div
|
|
11
|
+
class="ui-room-countdown__glass"
|
|
12
|
+
:class="{ 'ui-room-countdown__glass--out': live }"
|
|
13
|
+
aria-hidden="true"
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
<svg
|
|
17
|
+
class="ui-room-countdown__ring"
|
|
18
|
+
:class="{ 'ui-room-countdown__ring--out': live }"
|
|
19
|
+
viewBox="0 0 100 100"
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
>
|
|
22
|
+
<circle
|
|
23
|
+
class="ui-room-countdown__track"
|
|
24
|
+
cx="50"
|
|
25
|
+
cy="50"
|
|
26
|
+
r="46"
|
|
27
|
+
/>
|
|
28
|
+
<circle
|
|
29
|
+
v-if="!isFinished"
|
|
30
|
+
class="ui-room-countdown__progress"
|
|
31
|
+
cx="50"
|
|
32
|
+
cy="50"
|
|
33
|
+
r="46"
|
|
34
|
+
path-length="1"
|
|
35
|
+
:style="{ animationDuration: `${seconds}s` }"
|
|
36
|
+
/>
|
|
37
|
+
<g
|
|
38
|
+
v-if="!isFinished"
|
|
39
|
+
class="ui-room-countdown__head"
|
|
40
|
+
:style="{ animationDuration: `${seconds}s` }"
|
|
41
|
+
>
|
|
42
|
+
<circle
|
|
43
|
+
cx="50"
|
|
44
|
+
cy="4"
|
|
45
|
+
r="2"
|
|
46
|
+
/>
|
|
47
|
+
</g>
|
|
48
|
+
<circle
|
|
49
|
+
v-if="isStarting"
|
|
50
|
+
class="ui-room-countdown__spinner"
|
|
51
|
+
cx="50"
|
|
52
|
+
cy="50"
|
|
53
|
+
r="46"
|
|
54
|
+
path-length="1"
|
|
55
|
+
/>
|
|
56
|
+
</svg>
|
|
57
|
+
|
|
58
|
+
<Transition
|
|
59
|
+
name="ui-room-countdown-digit"
|
|
60
|
+
mode="out-in"
|
|
61
|
+
>
|
|
62
|
+
<span
|
|
63
|
+
v-if="!isFinished"
|
|
64
|
+
:key="remaining"
|
|
65
|
+
class="ui-room-countdown__digit"
|
|
66
|
+
>
|
|
67
|
+
{{ remaining }}
|
|
68
|
+
</span>
|
|
69
|
+
</Transition>
|
|
70
|
+
|
|
71
|
+
<span
|
|
72
|
+
v-if="isFinished"
|
|
73
|
+
class="ui-room-countdown__label"
|
|
74
|
+
>
|
|
75
|
+
<span
|
|
76
|
+
v-if="live"
|
|
77
|
+
class="ui-room-countdown__rec"
|
|
78
|
+
aria-hidden="true"
|
|
79
|
+
/>
|
|
80
|
+
{{ label }}
|
|
81
|
+
</span>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div
|
|
85
|
+
v-if="$slots.action"
|
|
86
|
+
class="ui-room-countdown__action"
|
|
87
|
+
>
|
|
88
|
+
<slot name="action" />
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</template>
|
|
92
|
+
|
|
93
|
+
<script setup lang="ts">
|
|
94
|
+
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
95
|
+
|
|
96
|
+
const props = withDefaults(defineProps<{
|
|
97
|
+
seconds?: number
|
|
98
|
+
label?: string
|
|
99
|
+
size?: 'sm' | 'md' | 'lg'
|
|
100
|
+
finished?: boolean
|
|
101
|
+
live?: boolean
|
|
102
|
+
}>(), {
|
|
103
|
+
seconds: 5,
|
|
104
|
+
label: 'You are live',
|
|
105
|
+
size: 'md',
|
|
106
|
+
finished: false,
|
|
107
|
+
live: false,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const emit = defineEmits<{
|
|
111
|
+
tick: [remaining: number]
|
|
112
|
+
finished: []
|
|
113
|
+
}>()
|
|
114
|
+
|
|
115
|
+
const remaining = ref(props.seconds)
|
|
116
|
+
let timer: ReturnType<typeof setInterval> | undefined
|
|
117
|
+
|
|
118
|
+
const isFinished = computed(() => props.finished || remaining.value <= 0)
|
|
119
|
+
|
|
120
|
+
const isStarting = computed(() => isFinished.value && !props.live)
|
|
121
|
+
|
|
122
|
+
const sizeValue = computed(() => ({
|
|
123
|
+
sm: '96px',
|
|
124
|
+
md: '200px',
|
|
125
|
+
lg: '288px',
|
|
126
|
+
}[props.size]))
|
|
127
|
+
|
|
128
|
+
function stop () {
|
|
129
|
+
clearInterval(timer)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
watch(isFinished, (value) => {
|
|
133
|
+
if (!value) return
|
|
134
|
+
|
|
135
|
+
stop()
|
|
136
|
+
emit('finished')
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
onMounted(() => {
|
|
140
|
+
if (isFinished.value) return
|
|
141
|
+
|
|
142
|
+
timer = setInterval(() => {
|
|
143
|
+
remaining.value -= 1
|
|
144
|
+
emit('tick', remaining.value)
|
|
145
|
+
|
|
146
|
+
if (remaining.value <= 0) stop()
|
|
147
|
+
}, 1000)
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
onBeforeUnmount(stop)
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
<style scoped>
|
|
154
|
+
@reference '@livestorm/ui-tokens/output/supernova/index.css';
|
|
155
|
+
|
|
156
|
+
.ui-room-countdown {
|
|
157
|
+
@apply flex flex-col items-center gap-6 text-text-neutral-base;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.ui-room-countdown__dial {
|
|
161
|
+
@apply relative grid place-items-center;
|
|
162
|
+
width: var(--ui-room-countdown-size);
|
|
163
|
+
height: var(--ui-room-countdown-size);
|
|
164
|
+
font-size: var(--ui-room-countdown-size);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.ui-room-countdown__glass {
|
|
168
|
+
@apply absolute inset-[7%] rounded-full bg-surface-neutral-alpha-100;
|
|
169
|
+
backdrop-filter: blur(var(--blur-blur-lg));
|
|
170
|
+
transition: all 0.8s cubic-bezier(0.16, 1, 0.3, 1);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.ui-room-countdown__glass::after {
|
|
174
|
+
@apply absolute inset-0 rounded-full content-[''];
|
|
175
|
+
background: radial-gradient(circle, var(--color-surface-neutral-alpha-200) 0%, transparent 70%);
|
|
176
|
+
animation: ui-room-countdown-breath 1.4s ease-in-out infinite;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.ui-room-countdown__glass--out {
|
|
180
|
+
@apply opacity-0;
|
|
181
|
+
transform: scale(1.2);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.ui-room-countdown__ring {
|
|
185
|
+
@apply absolute inset-0 h-full w-full -rotate-90 overflow-visible;
|
|
186
|
+
fill: none;
|
|
187
|
+
stroke: currentColor;
|
|
188
|
+
stroke-width: 1;
|
|
189
|
+
stroke-linecap: round;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.ui-room-countdown__track {
|
|
193
|
+
@apply opacity-20;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.ui-room-countdown__ring--out {
|
|
197
|
+
@apply opacity-0;
|
|
198
|
+
transform: rotate(-90deg) scale(1.3);
|
|
199
|
+
transition: all 0.8s cubic-bezier(0.16, 1, 0.3, 1);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.ui-room-countdown__progress {
|
|
203
|
+
stroke-dasharray: 1;
|
|
204
|
+
animation: ui-room-countdown-drain linear forwards;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.ui-room-countdown__spinner {
|
|
208
|
+
stroke-dasharray: 0.18 0.82;
|
|
209
|
+
transform-origin: 50px 50px;
|
|
210
|
+
animation: ui-room-countdown-spin 1.4s linear infinite;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.ui-room-countdown__head {
|
|
214
|
+
fill: currentColor;
|
|
215
|
+
stroke: none;
|
|
216
|
+
transform-origin: 50px 50px;
|
|
217
|
+
animation: ui-room-countdown-orbit linear forwards;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.ui-room-countdown__action {
|
|
221
|
+
@apply flex items-center justify-center;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.ui-room-countdown__digit {
|
|
225
|
+
@apply absolute inset-0 grid place-items-center leading-none;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.ui-room-countdown__label {
|
|
229
|
+
@apply absolute inset-0 flex items-center justify-center leading-none;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.ui-room-countdown__digit {
|
|
233
|
+
font-size: 0.44em;
|
|
234
|
+
font-weight: 600;
|
|
235
|
+
font-variant-numeric: tabular-nums;
|
|
236
|
+
letter-spacing: -0.03em;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.ui-room-countdown__label {
|
|
240
|
+
font-size: 0.095em;
|
|
241
|
+
font-weight: 500;
|
|
242
|
+
letter-spacing: -0.01em;
|
|
243
|
+
white-space: nowrap;
|
|
244
|
+
gap: 0.5em;
|
|
245
|
+
animation: ui-room-countdown-zoom 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.25s backwards;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.ui-room-countdown__rec {
|
|
249
|
+
@apply relative h-[0.5em] w-[0.5em] shrink-0 rounded-full bg-actions-danger-idle;
|
|
250
|
+
transform-origin: right center;
|
|
251
|
+
animation: ui-room-countdown-rec-in 0.45s cubic-bezier(0.16, 1, 0.3, 1) 0.4s backwards;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.ui-room-countdown__rec::after {
|
|
255
|
+
@apply absolute inset-0 rounded-full bg-actions-danger-idle content-[''];
|
|
256
|
+
animation: ui-room-countdown-rec-ping 1.8s cubic-bezier(0.16, 1, 0.3, 1) 0.6s infinite;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.ui-room-countdown-digit-enter-active {
|
|
260
|
+
animation: ui-room-countdown-digit-in 0.65s cubic-bezier(0.16, 1, 0.3, 1);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.ui-room-countdown-digit-leave-active {
|
|
264
|
+
transition: all 0.22s cubic-bezier(0.7, 0, 0.84, 0);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.ui-room-countdown-digit-leave-to {
|
|
268
|
+
opacity: 0;
|
|
269
|
+
filter: blur(0.03em);
|
|
270
|
+
transform: scale(0.6);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@keyframes ui-room-countdown-drain {
|
|
274
|
+
to {
|
|
275
|
+
stroke-dashoffset: 1;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@keyframes ui-room-countdown-digit-in {
|
|
280
|
+
0% {
|
|
281
|
+
opacity: 0;
|
|
282
|
+
filter: blur(0.03em);
|
|
283
|
+
transform: scale(1.3);
|
|
284
|
+
}
|
|
285
|
+
45% {
|
|
286
|
+
opacity: 1;
|
|
287
|
+
filter: blur(0);
|
|
288
|
+
}
|
|
289
|
+
70% {
|
|
290
|
+
transform: scale(0.98);
|
|
291
|
+
}
|
|
292
|
+
100% {
|
|
293
|
+
opacity: 1;
|
|
294
|
+
filter: blur(0);
|
|
295
|
+
transform: scale(1);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
@keyframes ui-room-countdown-breath {
|
|
300
|
+
0%,
|
|
301
|
+
100% {
|
|
302
|
+
opacity: 0.4;
|
|
303
|
+
transform: scale(0.9);
|
|
304
|
+
}
|
|
305
|
+
50% {
|
|
306
|
+
opacity: 0.9;
|
|
307
|
+
transform: scale(1.05);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
@keyframes ui-room-countdown-spin {
|
|
312
|
+
to {
|
|
313
|
+
transform: rotate(360deg);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
@keyframes ui-room-countdown-orbit {
|
|
318
|
+
to {
|
|
319
|
+
transform: rotate(360deg);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
@keyframes ui-room-countdown-zoom {
|
|
324
|
+
from {
|
|
325
|
+
opacity: 0;
|
|
326
|
+
filter: blur(0.02em);
|
|
327
|
+
transform: scale(0.88);
|
|
328
|
+
}
|
|
329
|
+
to {
|
|
330
|
+
opacity: 1;
|
|
331
|
+
filter: blur(0);
|
|
332
|
+
transform: scale(1);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
@keyframes ui-room-countdown-rec-in {
|
|
337
|
+
from {
|
|
338
|
+
opacity: 0;
|
|
339
|
+
transform: scale(0.5);
|
|
340
|
+
margin-right: -1em;
|
|
341
|
+
}
|
|
342
|
+
to {
|
|
343
|
+
opacity: 1;
|
|
344
|
+
transform: scale(1);
|
|
345
|
+
margin-right: 0;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
@keyframes ui-room-countdown-rec-ping {
|
|
350
|
+
from {
|
|
351
|
+
opacity: 0.45;
|
|
352
|
+
transform: scale(1);
|
|
353
|
+
}
|
|
354
|
+
to {
|
|
355
|
+
opacity: 0;
|
|
356
|
+
transform: scale(2.2);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@media (prefers-reduced-motion: reduce) {
|
|
361
|
+
.ui-room-countdown__progress,
|
|
362
|
+
.ui-room-countdown__spinner,
|
|
363
|
+
.ui-room-countdown__label,
|
|
364
|
+
.ui-room-countdown__glass,
|
|
365
|
+
.ui-room-countdown__glass::after,
|
|
366
|
+
.ui-room-countdown__rec,
|
|
367
|
+
.ui-room-countdown__rec::after,
|
|
368
|
+
.ui-room-countdown__head,
|
|
369
|
+
.ui-room-countdown__ring--out,
|
|
370
|
+
.ui-room-countdown-digit-enter-active,
|
|
371
|
+
.ui-room-countdown-digit-leave-active {
|
|
372
|
+
animation: none;
|
|
373
|
+
transition: none;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
</style>
|
|
@@ -6,8 +6,11 @@ import UiButton from '../UiButton/UiButton.vue'
|
|
|
6
6
|
|
|
7
7
|
const props = withDefaults(defineProps<{
|
|
8
8
|
openMenuLabel?: string
|
|
9
|
+
/** The shell canvas (gradient and overlays). Off when the host paints its own surface. */
|
|
10
|
+
showBackground?: boolean
|
|
9
11
|
}>(), {
|
|
10
12
|
openMenuLabel: 'Menu',
|
|
13
|
+
showBackground: true,
|
|
11
14
|
})
|
|
12
15
|
|
|
13
16
|
const slots = useSlots() as {
|
|
@@ -29,7 +32,10 @@ const fallbackLabel = computed(() => menuLabel.value ?? props.openMenuLabel)
|
|
|
29
32
|
class="ui-shell h-dvh flex flex-col relative"
|
|
30
33
|
data-sizes-primitives="Mode-1"
|
|
31
34
|
>
|
|
32
|
-
<div
|
|
35
|
+
<div
|
|
36
|
+
v-if="showBackground"
|
|
37
|
+
class="ui-shell-backgrounds absolute inset-0 grid grid-cols-1 grid-rows-1 z-0"
|
|
38
|
+
>
|
|
33
39
|
<div class="ui-shell-background col-span-full row-span-full bg-gradient-to-tl from-surface-primary-100 to-surface-primary-300" />
|
|
34
40
|
<div class="ui-shell-background col-span-full row-span-full bg-surface-neutral-invert-alpha-600" />
|
|
35
41
|
<div class="ui-shell-background col-span-full row-span-full bg-surface-primary-alpha-100" />
|
|
@@ -44,7 +50,7 @@ const fallbackLabel = computed(() => menuLabel.value ?? props.openMenuLabel)
|
|
|
44
50
|
<div class="flex-1 flex w-full relative min-h-0">
|
|
45
51
|
<div
|
|
46
52
|
v-if="slots.sidemenu"
|
|
47
|
-
class="dashboard-sidebar md:flex shrink-0 text-text-neutral-base flex z-40"
|
|
53
|
+
class="dashboard-sidebar md:flex shrink-0 text-text-neutral-base flex z-40 [anchor-name:--ui-shell-side-menu]"
|
|
48
54
|
>
|
|
49
55
|
<slot
|
|
50
56
|
name="sidemenu"
|
|
@@ -52,7 +58,7 @@ const fallbackLabel = computed(() => menuLabel.value ?? props.openMenuLabel)
|
|
|
52
58
|
/>
|
|
53
59
|
</div>
|
|
54
60
|
|
|
55
|
-
<div class="dashboard-content flex-1 flex flex-col z-10 min-h-0">
|
|
61
|
+
<div class="dashboard-content flex-1 flex flex-col z-10 min-w-0 min-h-0">
|
|
56
62
|
<!--
|
|
57
63
|
Fallback mobile menu trigger. The hamburger normally lives in
|
|
58
64
|
UiPageHeader, but a page can render without a header — leaving no way
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type { Slot } from 'vue'
|
|
2
|
+
import type { ComponentPublicInstance, Slot } from 'vue'
|
|
3
3
|
import type { SideMenuCollapsedItem, SideMenuItemProps, SideMenuMoreItem } from './types'
|
|
4
4
|
import UiSideMenuItem from './UiSideMenuItem.vue'
|
|
5
5
|
import UiLogo from '../UiLogo/UiLogo.vue'
|
|
@@ -7,10 +7,15 @@ import UiButton from '../UiButton/UiButton.vue'
|
|
|
7
7
|
import UiPopover from '../UiPopover/UiPopover.vue'
|
|
8
8
|
import UiPopoverTrigger from '../UiPopover/UiPopoverTrigger.vue'
|
|
9
9
|
import UiPopoverContent from '../UiPopover/UiPopoverContent.vue'
|
|
10
|
+
import UiTooltipProvider from '../UiTooltip/UiTooltipProvider.vue'
|
|
11
|
+
import UiTooltip from '../UiTooltip/UiTooltip.vue'
|
|
12
|
+
import UiTooltipTrigger from '../UiTooltip/UiTooltipTrigger.vue'
|
|
13
|
+
import UiTooltipContent from '../UiTooltip/UiTooltipContent.vue'
|
|
10
14
|
import { useMobileMenu } from '../../composables/useMobileMenu'
|
|
15
|
+
import { usePullGesture } from '../../composables/usePullGesture'
|
|
11
16
|
import { useTranslate } from '../../utils/i18n'
|
|
12
|
-
import { focusFirstMenuItem } from '../../utils'
|
|
13
|
-
import { computed, onBeforeUnmount, onMounted, provide, ref } from 'vue'
|
|
17
|
+
import { focusFirstMenuItem } from '../../utils/a11y'
|
|
18
|
+
import { computed, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
|
|
14
19
|
import { SIDE_MENU_LAYOUT_KEY } from './injection'
|
|
15
20
|
const { close, isOpen } = useMobileMenu()
|
|
16
21
|
const translate = useTranslate()
|
|
@@ -81,6 +86,8 @@ const slots = defineSlots<{
|
|
|
81
86
|
* `close` callback to dismiss the popover (e.g. when a nested popover opens).
|
|
82
87
|
*/
|
|
83
88
|
collapsedMenuExtra?(props: { close: () => void }): Slot
|
|
89
|
+
/** Tooltip shown under the logo while it is pulled, with the stage reached so far. */
|
|
90
|
+
logoPullHint?(props: { stage: number }): Slot
|
|
84
91
|
}>()
|
|
85
92
|
|
|
86
93
|
const props = withDefaults(defineProps<{
|
|
@@ -105,6 +112,16 @@ const props = withDefaults(defineProps<{
|
|
|
105
112
|
*/
|
|
106
113
|
moreBadge?: number | boolean
|
|
107
114
|
showLivestormLogo?: boolean
|
|
115
|
+
/**
|
|
116
|
+
* Pointer travel (px, ascending) at which pulling the logo, in any
|
|
117
|
+
* direction, reaches each stage; `logoPull` emits the stage reached on
|
|
118
|
+
* release. Empty disables the gesture.
|
|
119
|
+
*/
|
|
120
|
+
logoPullStages?: number[]
|
|
121
|
+
/** Travel (px) after which the pulled logo starts resisting; defaults to the last stage. */
|
|
122
|
+
logoPullResistFrom?: number
|
|
123
|
+
/** Visible travel the resisting logo tends toward; defaults to five times the last stage. */
|
|
124
|
+
logoPullMaxOffset?: number
|
|
108
125
|
// Accessibility labels
|
|
109
126
|
logoAlt?: string
|
|
110
127
|
closeMenuLabel?: string
|
|
@@ -116,6 +133,9 @@ const props = withDefaults(defineProps<{
|
|
|
116
133
|
organizationId?: string
|
|
117
134
|
}>(), {
|
|
118
135
|
showLivestormLogo: true,
|
|
136
|
+
logoPullStages: () => [],
|
|
137
|
+
logoPullResistFrom: undefined,
|
|
138
|
+
logoPullMaxOffset: undefined,
|
|
119
139
|
logoAlt: 'Livestorm',
|
|
120
140
|
closeMenuLabel: 'Close navigation menu',
|
|
121
141
|
mainNavigationLabel: 'Main navigation',
|
|
@@ -162,7 +182,53 @@ const hasCollapsedMenu = computed(
|
|
|
162
182
|
() => (!!props.collapsedMenuItems && props.collapsedMenuItems.length > 0) || !!slots.collapsedMenuExtra,
|
|
163
183
|
)
|
|
164
184
|
|
|
185
|
+
const emit = defineEmits<{
|
|
186
|
+
logoPull: [stage: number]
|
|
187
|
+
}>()
|
|
188
|
+
|
|
189
|
+
const pull = usePullGesture({
|
|
190
|
+
stages: () => props.logoPullStages,
|
|
191
|
+
resistFrom: () => props.logoPullResistFrom,
|
|
192
|
+
maxOffset: () => props.logoPullMaxOffset,
|
|
193
|
+
onRelease: stage => emit('logoPull', stage),
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
// A lean toward the pull and a size step per stage make the gesture legible;
|
|
197
|
+
// grabbing shrinks the logo a touch, as if lifted out of its socket.
|
|
198
|
+
const LOGO_PULL_DEG_PER_PX = 0.15
|
|
199
|
+
const LOGO_PULL_MAX_DEG = 30
|
|
200
|
+
const LOGO_PULL_GRAB_SHRINK_PCT = 4
|
|
201
|
+
const LOGO_PULL_STAGE_GROWTH_PCT = 6
|
|
202
|
+
|
|
203
|
+
const logoPullStyle = computed(() => {
|
|
204
|
+
if (!pull.enabled.value) return undefined
|
|
205
|
+
const { x, y } = pull.offset.value
|
|
206
|
+
const shrink = pull.isPulling.value ? LOGO_PULL_GRAB_SHRINK_PCT : 0
|
|
207
|
+
const lean = Math.max(-LOGO_PULL_MAX_DEG, Math.min(LOGO_PULL_MAX_DEG, x * LOGO_PULL_DEG_PER_PX))
|
|
208
|
+
return {
|
|
209
|
+
translate: `${x}px ${y}px`,
|
|
210
|
+
rotate: `${lean}deg`,
|
|
211
|
+
scale: String((100 - shrink + pull.stage.value * LOGO_PULL_STAGE_GROWTH_PCT) / 100),
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
// Each new stage ticks: a quick overshoot of the logo and a haptic where
|
|
216
|
+
// supported. Reduced motion keeps the haptic only.
|
|
217
|
+
const logo = ref<ComponentPublicInstance | null>(null)
|
|
218
|
+
watch(pull.stage, (stage, previous) => {
|
|
219
|
+
if (stage <= previous) return
|
|
220
|
+
if ('vibrate' in navigator) navigator.vibrate(10)
|
|
221
|
+
if (window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) return
|
|
222
|
+
const el = logo.value?.$el as HTMLElement | undefined
|
|
223
|
+
el?.animate?.(
|
|
224
|
+
[{ transform: 'scale(1)' }, { transform: 'scale(1.18)', offset: 0.4 }, { transform: 'scale(1)' }],
|
|
225
|
+
{ duration: 220, easing: 'ease-out' },
|
|
226
|
+
)
|
|
227
|
+
})
|
|
228
|
+
|
|
165
229
|
function handleLogoClick (event: MouseEvent) {
|
|
230
|
+
// The browser still fires a click after a pull; keep it off the click count.
|
|
231
|
+
if (pull.consumeDrag()) return
|
|
166
232
|
if (event.detail === 4) {
|
|
167
233
|
if (navigator.clipboard && props.organizationId) {
|
|
168
234
|
navigator.clipboard.writeText(props.organizationId)
|
|
@@ -182,24 +248,63 @@ function handleLogoClick (event: MouseEvent) {
|
|
|
182
248
|
<!-- Skip link for accessibility -->
|
|
183
249
|
<router-link
|
|
184
250
|
to="/"
|
|
185
|
-
class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:bg-
|
|
251
|
+
class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:bg-actions-primary-idle focus:text-text-neutral-invert-base focus:px-4 focus:py-2 focus:rounded-row bg-surface-overlay-alpha"
|
|
186
252
|
>
|
|
187
253
|
{{ skipToMainContentLabel }}
|
|
188
254
|
</router-link>
|
|
189
255
|
<!-- Top -->
|
|
190
256
|
<div class="flex flex-col md:items-center gap-8">
|
|
191
257
|
<div class="flex items-center justify-between">
|
|
192
|
-
<
|
|
258
|
+
<div
|
|
193
259
|
v-if="showLivestormLogo"
|
|
194
|
-
|
|
195
|
-
:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
260
|
+
class="relative ml-4 md:ml-0"
|
|
261
|
+
:class="{ 'z-10': pull.enabled.value }"
|
|
262
|
+
>
|
|
263
|
+
<div
|
|
264
|
+
v-if="pull.enabled.value"
|
|
265
|
+
class="logo-pull-socket absolute top-0 left-0 w-10 h-10 rounded-[35%] pointer-events-none"
|
|
266
|
+
:class="{ 'logo-pull-socket-visible': pull.isPulling.value }"
|
|
267
|
+
/>
|
|
268
|
+
<!-- Controlled tooltip: shown only while pulling, never on hover. -->
|
|
269
|
+
<UiTooltipProvider>
|
|
270
|
+
<UiTooltip :open="!!slots.logoPullHint && pull.isPulling.value">
|
|
271
|
+
<UiTooltipTrigger as-child>
|
|
272
|
+
<div
|
|
273
|
+
:class="{
|
|
274
|
+
'logo-pull touch-none select-none cursor-grab': pull.enabled.value,
|
|
275
|
+
'logo-pull-active cursor-grabbing': pull.isPulling.value,
|
|
276
|
+
}"
|
|
277
|
+
:style="logoPullStyle"
|
|
278
|
+
@pointerdown="pull.onPointerDown"
|
|
279
|
+
@pointermove="pull.onPointerMove"
|
|
280
|
+
@pointerup="pull.onPointerUp"
|
|
281
|
+
@pointercancel="pull.onPointerCancel"
|
|
282
|
+
@click="handleLogoClick"
|
|
283
|
+
>
|
|
284
|
+
<UiLogo
|
|
285
|
+
ref="logo"
|
|
286
|
+
:height="2.5"
|
|
287
|
+
:width="2.5"
|
|
288
|
+
:themed="false"
|
|
289
|
+
:animated="false"
|
|
290
|
+
inverted="auto"
|
|
291
|
+
:label="logoAlt"
|
|
292
|
+
/>
|
|
293
|
+
</div>
|
|
294
|
+
</UiTooltipTrigger>
|
|
295
|
+
<UiTooltipContent
|
|
296
|
+
side="bottom"
|
|
297
|
+
:side-offset="8"
|
|
298
|
+
update-position-strategy="always"
|
|
299
|
+
>
|
|
300
|
+
<slot
|
|
301
|
+
name="logoPullHint"
|
|
302
|
+
:stage="pull.stage.value"
|
|
303
|
+
/>
|
|
304
|
+
</UiTooltipContent>
|
|
305
|
+
</UiTooltip>
|
|
306
|
+
</UiTooltipProvider>
|
|
307
|
+
</div>
|
|
203
308
|
<div class="md:hidden">
|
|
204
309
|
<UiButton
|
|
205
310
|
icon="i-ph-x"
|
|
@@ -311,14 +416,14 @@ function handleLogoClick (event: MouseEvent) {
|
|
|
311
416
|
:align="isMobile ? 'center' : 'end'"
|
|
312
417
|
:side-offset="8"
|
|
313
418
|
:collision-padding="16"
|
|
314
|
-
class="border-none bg-surface-neutral-300
|
|
419
|
+
class="border-none bg-surface-neutral-300 shadow-shadows-drop-shadow-2xl overflow-hidden data-[state=closed]:hidden"
|
|
315
420
|
:class="isMobile
|
|
316
421
|
? 'w-(--reka-popover-trigger-width)'
|
|
317
422
|
: 'w-[calc(var(--reka-popover-trigger-width)+2rem)]'"
|
|
318
423
|
data-colors-semantic="light"
|
|
319
424
|
@open-auto-focus="handleOpenAutoFocus"
|
|
320
425
|
>
|
|
321
|
-
<ul class="flex flex-col md:items-center gap-2
|
|
426
|
+
<ul class="flex flex-col md:items-center gap-2 px-1 py-2">
|
|
322
427
|
<li
|
|
323
428
|
v-for="item in collapsedMenuItems"
|
|
324
429
|
:key="`collapsed-menu-item-${item.label}`"
|
|
@@ -432,11 +537,11 @@ function handleLogoClick (event: MouseEvent) {
|
|
|
432
537
|
side="right"
|
|
433
538
|
align="end"
|
|
434
539
|
:side-offset="8"
|
|
435
|
-
class="border-none bg-surface-neutral-300
|
|
540
|
+
class="border-none bg-surface-neutral-300 shadow-shadows-drop-shadow-2xl overflow-hidden"
|
|
436
541
|
data-colors-semantic="light"
|
|
437
542
|
@open-auto-focus="handleOpenAutoFocus"
|
|
438
543
|
>
|
|
439
|
-
<div class="flex flex-col md:items-center gap-2
|
|
544
|
+
<div class="flex flex-col md:items-center gap-2 px-1 py-2">
|
|
440
545
|
<li
|
|
441
546
|
v-for="item in bottomMenuItems"
|
|
442
547
|
:key="`popover-menu-item-${item.label}`"
|
|
@@ -489,6 +594,38 @@ function handleLogoClick (event: MouseEvent) {
|
|
|
489
594
|
</template>
|
|
490
595
|
|
|
491
596
|
<style scoped>
|
|
597
|
+
/* Logo pull: free while dragging, springs back on release. */
|
|
598
|
+
.logo-pull {
|
|
599
|
+
transition:
|
|
600
|
+
translate 400ms cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
601
|
+
rotate 400ms cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
602
|
+
scale 150ms ease-out;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
.logo-pull-active {
|
|
606
|
+
transition: scale 150ms ease-out;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/* Recess left where the logo rests; lingers until the logo has landed. */
|
|
610
|
+
.logo-pull-socket {
|
|
611
|
+
background: rgb(0 0 0 / 0.12);
|
|
612
|
+
box-shadow: inset 0 1px 3px rgb(0 0 0 / 0.25);
|
|
613
|
+
opacity: 0;
|
|
614
|
+
transition: opacity 200ms ease 250ms;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.logo-pull-socket-visible {
|
|
618
|
+
opacity: 1;
|
|
619
|
+
transition-delay: 0ms;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
@media (prefers-reduced-motion: reduce) {
|
|
623
|
+
.logo-pull,
|
|
624
|
+
.logo-pull-socket {
|
|
625
|
+
transition: none;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
492
629
|
/* Hide the more menu by default */
|
|
493
630
|
.show-on-short-height-desktop-only {
|
|
494
631
|
display: none;
|