frappe-ui 1.0.0-beta.2 → 1.0.0-beta.21
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/experimental/FloatingWindow/FloatingWindow.cy.ts +328 -0
- package/experimental/FloatingWindow/FloatingWindow.vue +303 -0
- package/experimental/FloatingWindow/index.ts +8 -0
- package/experimental/FloatingWindow/types.ts +31 -0
- package/experimental/FloatingWindow/useFloatingWindow.ts +236 -0
- package/experimental/MultiEmailInput/MultiEmailInput.cy.ts +155 -0
- package/experimental/MultiEmailInput/MultiEmailInput.vue +472 -0
- package/experimental/MultiEmailInput/index.ts +17 -0
- package/experimental/MultiEmailInput/stories/AsyncSuggestions.vue +54 -0
- package/experimental/MultiEmailInput/stories/Basic.vue +18 -0
- package/experimental/MultiEmailInput/stories/CustomChip.vue +39 -0
- package/experimental/MultiEmailInput/stories/Labeling.vue +28 -0
- package/experimental/MultiEmailInput/types.ts +138 -0
- package/experimental/MultiEmailInput/utils.ts +60 -0
- package/experimental.ts +12 -0
- package/frappe/Billing/SignupBanner.vue +1 -1
- package/frappe/Billing/TrialBanner.vue +1 -1
- package/frappe/DataImport/DataImport.vue +1 -1
- package/frappe/DataImport/DataImportList.vue +1 -1
- package/frappe/DataImport/ImportSteps.vue +6 -6
- package/frappe/DataImport/MappingStep.vue +1 -1
- package/frappe/DataImport/PreviewStep.vue +9 -9
- package/frappe/DataImport/TemplateModal.vue +1 -1
- package/frappe/DataImport/UploadStep.vue +5 -5
- package/frappe/Filter/Filter.vue +1 -1
- package/frappe/Help/HelpModal.vue +1 -1
- package/frappe/Link/stories/Suffix.vue +2 -2
- package/frappe/Onboarding/GettingStartedBanner.vue +1 -1
- package/frappe/drive/components/AppSwitcher.vue +1 -1
- package/frappe/drive/components/InfoDialog.vue +3 -3
- package/frappe/drive/components/MoveDialog.vue +2 -2
- package/frappe/drive/components/Select/Select.vue +2 -2
- package/frappe/drive/components/ShareDialog.vue +1 -1
- package/frappe/telemetry/index.ts +88 -14
- package/frappe/telemetry/pulse.ts +78 -164
- package/frappe/telemetry/telemetry.test.ts +13 -79
- package/icons/IconPicker.vue +1 -1
- package/package.json +104 -34
- package/src/components/Alert/Alert.md +4 -0
- package/src/components/Alert/Alert.vue +4 -4
- package/src/components/Autocomplete/Autocomplete.vue +6 -6
- package/src/components/Avatar/Avatar.md +4 -0
- package/src/components/Avatar/Avatar.vue +23 -4
- package/src/components/Badge/Badge.api.md +1 -1
- package/src/components/Badge/Badge.cy.ts +34 -16
- package/src/components/Badge/Badge.md +20 -4
- package/src/components/Badge/Badge.vue +60 -45
- package/src/components/Badge/stories/CallMeta.vue +35 -0
- package/src/components/Badge/stories/EventStatus.vue +16 -0
- package/src/components/Badge/stories/ListStatus.vue +91 -0
- package/src/components/Badge/stories/Reactions.vue +33 -0
- package/src/components/Badge/stories/RowTags.vue +39 -0
- package/src/components/Badge/types.ts +1 -2
- package/src/components/BottomSheet/BottomSheet.api.md +57 -0
- package/src/components/BottomSheet/BottomSheet.vue +232 -0
- package/src/components/BottomSheet/index.ts +6 -0
- package/src/components/BottomSheet/types.ts +23 -0
- package/src/components/Breadcrumbs/Breadcrumbs.md +4 -0
- package/src/components/Breadcrumbs/Breadcrumbs.vue +3 -3
- package/src/components/Button/Button.api.md +37 -32
- package/src/components/Button/Button.cy.ts +18 -2
- package/src/components/Button/Button.md +20 -8
- package/src/components/Button/Button.vue +304 -284
- package/src/components/Button/stories/InlineActions.vue +10 -0
- package/src/components/Button/stories/LiveClassCard.vue +34 -0
- package/src/components/Button/stories/SectionAction.vue +17 -0
- package/src/components/Button/stories/SectionControls.vue +28 -0
- package/src/components/Button/stories/SelectionToolbar.vue +20 -0
- package/src/components/Button/stories/StackedActions.vue +10 -0
- package/src/components/Button/types.ts +38 -32
- package/src/components/Calendar/Calendar.api.md +16 -16
- package/src/components/Calendar/Calendar.vue +100 -73
- package/src/components/Calendar/CalendarDaily.vue +21 -20
- package/src/components/Calendar/CalendarMonthEvent.vue +30 -9
- package/src/components/Calendar/CalendarMonthly.vue +60 -39
- package/src/components/Calendar/CalendarTimeMarker.vue +9 -8
- package/src/components/Calendar/CalendarWeekDayEvent.vue +98 -42
- package/src/components/Calendar/CalendarWeekly.vue +77 -41
- package/src/components/Calendar/EventModalContent.vue +32 -16
- package/src/components/Calendar/NewEventModal.vue +19 -16
- package/src/components/Calendar/ShowMoreCalendarEvent.vue +11 -17
- package/src/components/Calendar/{calendarUtils.js → calendarUtils.ts} +76 -52
- package/src/components/Calendar/composables/{useCalendarData.js → useCalendarData.ts} +23 -11
- package/src/components/Calendar/composables/{useEventModal.js → useEventModal.ts} +16 -12
- package/src/components/Calendar/index.ts +12 -2
- package/src/components/Calendar/stories/CustomHeader.vue +1 -1
- package/src/components/Calendar/types.ts +106 -0
- package/src/components/Calendar/{useEventBase.js → useEventBase.ts} +40 -26
- package/src/components/Card.vue +2 -2
- package/src/components/Charts/ECharts.vue +1 -1
- package/src/components/Charts/NumberChart.vue +7 -7
- package/src/components/Charts/eChartOptions.ts +28 -13
- package/src/components/Checkbox/Checkbox.api.md +6 -0
- package/src/components/Checkbox/Checkbox.cy.ts +10 -2
- package/src/components/Checkbox/Checkbox.md +28 -0
- package/src/components/Checkbox/Checkbox.vue +9 -22
- package/src/components/Checkbox/stories/Group.vue +27 -0
- package/src/components/Checkbox/stories/HorizontalGroup.vue +24 -0
- package/src/components/Checkbox/stories/SettingRow.vue +23 -0
- package/src/components/Checkbox/stories/WithDescription.vue +27 -0
- package/src/components/Checkbox/types.ts +7 -0
- package/src/components/CodeEditor/CodeEditor.api.md +139 -0
- package/src/components/CodeEditor/CodeEditor.cy.ts +160 -0
- package/src/components/CodeEditor/CodeEditor.md +104 -0
- package/src/components/CodeEditor/CodeEditor.vue +556 -0
- package/src/components/CodeEditor/CodePreview.test.ts +49 -0
- package/src/components/CodeEditor/CodePreview.vue +45 -0
- package/src/components/CodeEditor/index.ts +17 -0
- package/src/components/CodeEditor/languages.ts +63 -0
- package/src/components/CodeEditor/stories/Default.vue +16 -0
- package/src/components/CodeEditor/stories/Labeling.vue +25 -0
- package/src/components/CodeEditor/stories/MaxHeight.vue +24 -0
- package/src/components/CodeEditor/stories/Preview.vue +36 -0
- package/src/components/CodeEditor/stories/Sizes.vue +15 -0
- package/src/components/CodeEditor/stories/Variants.vue +13 -0
- package/src/components/CodeEditor/theme.ts +272 -0
- package/src/components/CodeEditor/types.ts +69 -0
- package/src/components/Combobox/Combobox.api.md +19 -20
- package/src/components/Combobox/Combobox.cy.ts +54 -14
- package/src/components/Combobox/Combobox.md +4 -0
- package/src/components/Combobox/Combobox.vue +233 -247
- package/src/components/Combobox/ComboboxResults.vue +1 -1
- package/src/components/Combobox/stories/Clearable.vue +2 -2
- package/src/components/Combobox/stories/CreateNew.vue +1 -1
- package/src/components/Combobox/stories/Footer.vue +10 -2
- package/src/components/Combobox/stories/InDialog.vue +1 -1
- package/src/components/Combobox/types.ts +8 -29
- package/src/components/CommandPalette/CommandPaletteItem.vue +1 -1
- package/src/components/ContextMenu/ContextMenu.api.md +52 -0
- package/src/components/ContextMenu/ContextMenu.cy.ts +191 -0
- package/src/components/ContextMenu/ContextMenu.md +25 -0
- package/src/components/ContextMenu/ContextMenu.vue +106 -0
- package/src/components/ContextMenu/index.ts +2 -0
- package/src/components/ContextMenu/stories/FileList.vue +105 -0
- package/src/components/ContextMenu/stories/Groups.vue +95 -0
- package/src/components/ContextMenu/stories/Simple.vue +72 -0
- package/src/components/ContextMenu/types.ts +39 -0
- package/src/components/DatePicker/CalendarPanel.vue +128 -86
- package/src/components/DatePicker/DatePicker.vue +3 -9
- package/src/components/DatePicker/DateRangePicker.vue +4 -8
- package/src/components/DatePicker/DateTimePicker.cy.ts +4 -2
- package/src/components/DatePicker/DateTimePicker.vue +3 -9
- package/src/components/DatePicker/composables.ts +15 -37
- package/src/components/DatePicker/stories/Range.vue +1 -1
- package/src/components/DatePicker/types.ts +1 -1
- package/src/components/DesktopShell/DesktopShell.api.md +40 -0
- package/src/components/DesktopShell/DesktopShell.cy.ts +39 -0
- package/src/components/DesktopShell/DesktopShell.md +31 -0
- package/src/components/DesktopShell/DesktopShell.vue +81 -0
- package/src/components/DesktopShell/index.ts +3 -0
- package/src/components/DesktopShell/stories/Default.vue +97 -0
- package/src/components/DesktopShell/types.ts +2 -0
- package/src/components/Dialog/Dialog.api.md +7 -8
- package/src/components/Dialog/Dialog.md +4 -0
- package/src/components/Dialog/Dialog.vue +8 -7
- package/src/components/Dialog/stories/CommandPalette.vue +1 -1
- package/src/components/Dialog/stories/Wizard.vue +1 -1
- package/src/components/Dialogs.vue +11 -9
- package/src/components/Divider/Divider.api.md +1 -1
- package/src/components/Divider/Divider.md +4 -0
- package/src/components/Dropdown/Dropdown.api.md +10 -35
- package/src/components/Dropdown/Dropdown.md +10 -6
- package/src/components/Dropdown/Dropdown.vue +33 -47
- package/src/components/Dropdown/stories/{05_KebabMenu.vue → KebabMenu.vue} +3 -1
- package/src/components/Dropdown/stories/{06_UserMenu.vue → UserMenu.vue} +1 -1
- package/src/components/Dropdown/types.ts +25 -189
- package/src/components/Duration/Duration.api.md +92 -0
- package/src/components/Duration/Duration.cy.ts +183 -0
- package/src/components/Duration/Duration.md +98 -0
- package/src/components/Duration/Duration.vue +114 -0
- package/src/components/Duration/duration.ts +185 -0
- package/src/components/Duration/index.ts +8 -0
- package/src/components/Duration/stories/Default.vue +10 -0
- package/src/components/Duration/stories/Formats.vue +16 -0
- package/src/components/Duration/stories/RealWorld.vue +50 -0
- package/src/components/Duration/stories/Sizes.vue +15 -0
- package/src/components/Duration/stories/States.vue +21 -0
- package/src/components/Duration/types.ts +52 -0
- package/src/components/ErrorMessage/ErrorMessage.cy.ts +1 -1
- package/src/components/ErrorMessage/ErrorMessage.md +4 -0
- package/src/components/ErrorMessage/ErrorMessage.vue +1 -1
- package/src/components/FileUploader/FileUploader.api.md +36 -11
- package/src/components/FileUploader/FileUploader.cy.ts +66 -0
- package/src/components/FileUploader/FileUploader.md +4 -1
- package/src/components/FileUploader/FileUploader.vue +147 -106
- package/src/components/FileUploader/index.ts +6 -0
- package/src/components/FileUploader/types.ts +43 -0
- package/src/components/FormControl/FormControl.api.md +3 -4
- package/src/components/FormControl/FormControl.md +4 -0
- package/src/components/FormControl/stories/RealForm.vue +3 -3
- package/src/components/FormLabel.vue +5 -8
- package/src/components/HoverCard/HoverCard.api.md +100 -0
- package/src/components/HoverCard/HoverCard.cy.ts +103 -0
- package/src/components/HoverCard/HoverCard.md +52 -0
- package/src/components/HoverCard/HoverCard.vue +91 -0
- package/src/components/HoverCard/index.ts +2 -0
- package/src/components/HoverCard/stories/Arrow.vue +28 -0
- package/src/components/HoverCard/stories/Delays.vue +16 -0
- package/src/components/HoverCard/stories/Example.vue +28 -0
- package/src/components/HoverCard/types.ts +47 -0
- package/src/components/Icon/Icon.cy.ts +78 -0
- package/src/components/Icon/Icon.vue +50 -0
- package/src/components/Icon/index.ts +1 -0
- package/src/components/InputLabeling/InputDescription.vue +1 -1
- package/src/components/InputLabeling/InputError.vue +1 -1
- package/src/components/InputLabeling/InputLabel.vue +21 -7
- package/src/components/InputLabeling/RequiredIndicator.vue +1 -1
- package/src/components/ItemListRow/ItemListRow.vue +1 -1
- package/src/components/ItemListRow/stories/RowStates.vue +1 -1
- package/src/components/KeyboardShortcut.vue +4 -8
- package/src/components/KeyboardShortcutsModal/KeyboardShortcutsModal.api.md +22 -14
- package/src/components/KeyboardShortcutsModal/KeyboardShortcutsModal.vue +2 -2
- package/src/components/ListFilter/ListFilter.api.md +5 -6
- package/src/components/ListFilter/ListFilter.vue +161 -57
- package/src/components/ListFilter/NestedPopover.vue +17 -10
- package/src/components/ListFilter/SearchComplete.vue +31 -38
- package/src/components/ListItem.vue +1 -1
- package/src/components/ListView/ListEmptyState.vue +1 -1
- package/src/components/ListView/ListGroupHeader.vue +2 -2
- package/src/components/ListView/ListRow.vue +1 -1
- package/src/components/ListView/ListSelectBanner.vue +1 -1
- package/src/components/ListView/ListView.api.md +322 -6
- package/src/components/ListView/index.ts +25 -0
- package/src/components/ListView/stories/CustomList.vue +1 -1
- package/src/components/ListView/stories/GroupedRows.vue +1 -1
- package/src/components/LoadingIndicator.vue +13 -22
- package/src/components/LoadingText.vue +3 -13
- package/src/components/{Dropdown/DropdownMenuList.vue → Menu/Menu.vue} +110 -75
- package/src/components/{Dropdown/DropdownMenuItemContent.vue → Menu/MenuItemContent.vue} +23 -33
- package/src/components/{Dropdown/DropdownRenderContent.vue → Menu/MenuRenderContent.vue} +1 -1
- package/src/components/Menu/types.ts +225 -0
- package/src/components/{Dropdown → Menu}/utils.ts +36 -40
- package/src/components/MobileNav/MobileNav.api.md +70 -0
- package/src/components/MobileNav/MobileNav.cy.ts +89 -0
- package/src/components/MobileNav/MobileNav.md +34 -0
- package/src/components/MobileNav/MobileNav.vue +15 -0
- package/src/components/MobileNav/MobileNavItem.vue +125 -0
- package/src/components/MobileNav/index.ts +4 -0
- package/src/components/MobileNav/stories/Default.vue +40 -0
- package/src/components/MobileNav/types.ts +33 -0
- package/src/components/MobileShell/MobileShell.api.md +23 -0
- package/src/components/MobileShell/MobileShell.cy.ts +25 -0
- package/src/components/MobileShell/MobileShell.md +24 -0
- package/src/components/MobileShell/MobileShell.vue +41 -0
- package/src/components/MobileShell/index.ts +3 -0
- package/src/components/MobileShell/stories/Default.vue +75 -0
- package/src/components/MobileShell/types.ts +7 -0
- package/src/components/MonthPicker/MonthPicker.cy.ts +16 -0
- package/src/components/MonthPicker/MonthPicker.vue +19 -8
- package/src/components/MultiSelect/MultiSelect.api.md +3 -4
- package/src/components/MultiSelect/MultiSelect.md +42 -10
- package/src/components/MultiSelect/MultiSelect.vue +199 -227
- package/src/components/MultiSelect/MultiSelectResults.vue +1 -1
- package/src/components/MultiSelect/stories/Members.vue +1 -1
- package/src/components/MultiSelect/stories/TagsTrigger.vue +3 -3
- package/src/components/MultiSelect/types.ts +3 -3
- package/src/components/PageHeader/PageHeader.api.md +112 -0
- package/src/components/PageHeader/PageHeader.cy.ts +68 -0
- package/src/components/PageHeader/PageHeader.md +25 -0
- package/src/components/PageHeader/PageHeader.vue +13 -0
- package/src/components/PageHeader/PageHeaderBackButton.vue +29 -0
- package/src/components/PageHeader/PageHeaderBase.vue +51 -0
- package/src/components/PageHeader/PageHeaderMobile.vue +68 -0
- package/src/components/PageHeader/PageHeaderMobileTitle.vue +16 -0
- package/src/components/PageHeader/PageHeaderTarget.vue +13 -0
- package/src/components/PageHeader/PageHeaderTitle.vue +12 -0
- package/src/components/PageHeader/index.ts +7 -0
- package/src/components/PageHeader/stories/Default.vue +19 -0
- package/src/components/PageHeader/stories/Mobile.vue +24 -0
- package/src/components/PageHeader/target.ts +19 -0
- package/src/components/PageHeader/types.ts +19 -0
- package/src/components/Password/Password.md +4 -0
- package/src/components/Password/Password.vue +2 -2
- package/src/components/Popover/Popover.api.md +126 -42
- package/src/components/Popover/Popover.cy.ts +425 -41
- package/src/components/Popover/Popover.md +99 -4
- package/src/components/Popover/Popover.vue +288 -215
- package/src/components/Popover/index.ts +8 -1
- package/src/components/Popover/stories/Arrow.vue +16 -0
- package/src/components/Popover/stories/Bare.vue +20 -0
- package/src/components/Popover/stories/Click.vue +7 -4
- package/src/components/Popover/stories/Controlled.vue +22 -0
- package/src/components/Popover/stories/Dismissible.vue +19 -0
- package/src/components/Popover/stories/MatchTriggerWidth.vue +16 -0
- package/src/components/Popover/stories/SideAlign.vue +17 -0
- package/src/components/Popover/types.ts +101 -23
- package/src/components/Progress/Progress.cy.ts +2 -2
- package/src/components/Progress/Progress.md +4 -0
- package/src/components/Progress/Progress.vue +4 -4
- package/src/components/Rail/Rail.api.md +91 -0
- package/src/components/Rail/Rail.cy.ts +84 -0
- package/src/components/Rail/Rail.md +30 -0
- package/src/components/Rail/Rail.vue +16 -0
- package/src/components/Rail/RailItem.vue +134 -0
- package/src/components/Rail/RailItemBadge.vue +64 -0
- package/src/components/Rail/index.ts +2 -0
- package/src/components/Rail/stories/Default.vue +44 -0
- package/src/components/Rail/types.ts +37 -0
- package/src/components/Rating/Rating.md +4 -0
- package/src/components/Rating/Rating.vue +5 -8
- package/src/components/Rating/stories/CustomSlot.vue +2 -2
- package/src/components/ScrollArea/ScrollArea.api.md +59 -0
- package/src/components/ScrollArea/ScrollArea.vue +46 -0
- package/src/components/ScrollArea/ScrollBar.vue +101 -0
- package/src/components/ScrollArea/index.ts +2 -0
- package/src/components/Select/Select.cy.ts +16 -15
- package/src/components/Select/Select.md +4 -0
- package/src/components/Select/Select.vue +217 -203
- package/src/components/Select/stories/Example.vue +4 -3
- package/src/components/Select/stories/States.vue +1 -1
- package/src/components/Select/stories/TriggerSlots.vue +2 -2
- package/src/components/Select/utils.ts +4 -3
- package/src/components/SettingsDialog/SettingsBody.vue +23 -0
- package/src/components/SettingsDialog/SettingsContent.vue +7 -0
- package/src/components/SettingsDialog/SettingsDialog.api.md +273 -0
- package/src/components/SettingsDialog/SettingsDialog.cy.ts +126 -0
- package/src/components/SettingsDialog/SettingsDialog.md +43 -0
- package/src/components/SettingsDialog/SettingsDialog.vue +76 -0
- package/src/components/SettingsDialog/SettingsHeader.vue +36 -0
- package/src/components/SettingsDialog/SettingsNavGroup.vue +20 -0
- package/src/components/SettingsDialog/SettingsNavItem.vue +33 -0
- package/src/components/SettingsDialog/SettingsPanel.cy.ts +77 -0
- package/src/components/SettingsDialog/SettingsPanel.vue +26 -0
- package/src/components/SettingsDialog/SettingsRow.vue +52 -0
- package/src/components/SettingsDialog/SettingsSidebar.vue +16 -0
- package/src/components/SettingsDialog/index.ts +10 -0
- package/src/components/SettingsDialog/stories/Default.vue +99 -0
- package/src/components/SettingsDialog/stories/PanelBasic.vue +52 -0
- package/src/components/SettingsDialog/stories/panels/NotificationsPanel.vue +57 -0
- package/src/components/SettingsDialog/stories/panels/PreferencesPanel.vue +57 -0
- package/src/components/SettingsDialog/stories/panels/ProfilePanel.vue +38 -0
- package/src/components/SettingsDialog/stories/panels/UsersPanel.vue +83 -0
- package/src/components/SettingsDialog/types.ts +21 -0
- package/src/components/Sidebar/Sidebar.api.md +124 -65
- package/src/components/Sidebar/Sidebar.cy.ts +127 -76
- package/src/components/Sidebar/Sidebar.md +47 -3
- package/src/components/Sidebar/Sidebar.vue +64 -56
- package/src/components/Sidebar/SidebarCollapseToggle.vue +23 -0
- package/src/components/Sidebar/SidebarHeader.vue +76 -52
- package/src/components/Sidebar/SidebarItem.vue +159 -95
- package/src/components/Sidebar/SidebarItemIcon.vue +25 -0
- package/src/components/Sidebar/SidebarLabel.vue +34 -0
- package/src/components/Sidebar/SidebarSection.vue +29 -14
- package/src/components/Sidebar/index.ts +13 -2
- package/src/components/Sidebar/stories/Collapsed.vue +40 -0
- package/src/components/Sidebar/stories/Default.vue +153 -0
- package/src/components/Sidebar/stories/Legacy.vue +36 -0
- package/src/components/Sidebar/types.ts +105 -20
- package/src/components/Skeleton/Skeleton.cy.ts +21 -0
- package/src/components/Skeleton/Skeleton.md +21 -0
- package/src/components/Skeleton/Skeleton.vue +6 -0
- package/src/components/Skeleton/index.ts +1 -0
- package/src/components/Skeleton/stories/Card.vue +12 -0
- package/src/components/Skeleton/stories/List.vue +15 -0
- package/src/components/Skeleton/stories/Text.vue +11 -0
- package/src/components/Slider/Slider.api.md +1 -1
- package/src/components/Slider/Slider.cy.ts +29 -0
- package/src/components/Slider/Slider.md +10 -0
- package/src/components/Slider/Slider.vue +37 -9
- package/src/components/Slider/stories/NegativeValues.vue +12 -0
- package/src/components/Slider/types.ts +1 -1
- package/src/components/Spinner/Spinner.api.md +32 -0
- package/src/components/Spinner/Spinner.cy.ts +87 -0
- package/src/components/Spinner/Spinner.md +21 -0
- package/src/components/Spinner/Spinner.vue +168 -0
- package/src/components/Spinner/index.ts +2 -0
- package/src/components/Spinner/stories/InContext.vue +49 -0
- package/src/components/Spinner/stories/Sizes.vue +12 -0
- package/src/components/Spinner/stories/Themes.vue +10 -0
- package/src/components/Spinner/stories/Track.vue +12 -0
- package/src/components/Spinner/types.ts +14 -0
- package/src/components/Switch/Switch.md +4 -0
- package/src/components/Switch/Switch.vue +6 -23
- package/src/components/TabButtons/Pill.vue +161 -0
- package/src/components/TabButtons/TabButtons.api.md +52 -2
- package/src/components/TabButtons/TabButtons.cy.ts +18 -5
- package/src/components/TabButtons/TabButtons.md +49 -0
- package/src/components/TabButtons/TabButtons.vue +207 -109
- package/src/components/TabButtons/index.ts +11 -1
- package/src/components/TabButtons/pillTypes.ts +43 -0
- package/src/components/TabButtons/stories/PrefixSuffix.vue +65 -0
- package/src/components/TabButtons/stories/Sizes.vue +26 -0
- package/src/components/TabButtons/stories/Variants.vue +40 -0
- package/src/components/TabButtons/stories/Vertical.vue +64 -0
- package/src/components/TabButtons/types.ts +49 -0
- package/src/components/Tabs/Tabs.md +4 -0
- package/src/components/Tabs/Tabs.vue +1 -1
- package/src/components/TextEditor/TextEditor.cy.ts +1 -1
- package/src/components/TextEditor/TextEditor.md +3 -0
- package/src/components/TextEditor/TextEditor.vue +7 -4
- package/src/components/TextEditor/components/CodeBlockComponent.vue +4 -194
- package/src/components/TextEditor/components/FontColor.vue +1 -1
- package/src/components/TextEditor/components/LinkPopup.vue +1 -1
- package/src/components/TextEditor/components/MediaNodeView.vue +17 -17
- package/src/components/TextEditor/components/MentionList.vue +1 -1
- package/src/components/TextEditor/components/TextEditorBubbleMenu.vue +14 -5
- package/src/components/TextEditor/components/TextEditorFixedMenu.vue +3 -3
- package/src/components/TextEditor/components/{Menu.vue → TextEditorMenu.vue} +3 -3
- package/src/components/TextEditor/extensions/iframe/InsertIframe.vue +2 -2
- package/src/components/TextEditor/extensions/iframe/iframe-extension.ts +62 -19
- package/src/components/TextEditor/extensions/image-group/ImageGroupNodeView.vue +1 -1
- package/src/components/TextEditor/extensions/image-group/ImageGroupUploadDialog.vue +4 -4
- package/src/components/TextEditor/extensions/suggestion/SuggestionList.vue +1 -1
- package/src/components/TextEditor/extensions/toc-node/TocNodeView.vue +1 -1
- package/src/components/TextEditor/hljs-github.css +197 -0
- package/src/components/TextEditor/index.ts +13 -0
- package/src/components/TextInput/TextInput.cy.ts +8 -3
- package/src/components/TextInput/TextInput.md +4 -0
- package/src/components/TextInput/TextInput.vue +11 -15
- package/src/components/TextInput/stories/Slots.vue +1 -1
- package/src/components/Textarea/Textarea.cy.ts +1 -1
- package/src/components/Textarea/Textarea.md +4 -0
- package/src/components/Textarea/Textarea.vue +11 -15
- package/src/components/ThemeSwitcher/ThemePreview.vue +74 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.api.md +82 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.cy.ts +101 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.md +70 -0
- package/src/components/ThemeSwitcher/ThemeSwitcher.vue +145 -0
- package/src/components/ThemeSwitcher/index.ts +2 -0
- package/src/components/ThemeSwitcher/previews/PreviewWindow.vue +74 -0
- package/src/components/ThemeSwitcher/stories/Branded.vue +12 -0
- package/src/components/ThemeSwitcher/stories/Default.vue +7 -0
- package/src/components/ThemeSwitcher/stories/Menu.vue +53 -0
- package/src/components/ThemeSwitcher/stories/Toggle.vue +25 -0
- package/src/components/ThemeSwitcher/types.ts +35 -0
- package/src/components/TimePicker/TimePicker.api.md +67 -15
- package/src/components/TimePicker/TimePicker.cy.ts +130 -14
- package/src/components/TimePicker/TimePicker.md +6 -0
- package/src/components/TimePicker/TimePicker.vue +74 -19
- package/src/components/TimePicker/stories/Labeling.vue +21 -0
- package/src/components/TimePicker/stories/Range.vue +1 -1
- package/src/components/TimePicker/stories/SizesAndVariants.vue +23 -0
- package/src/components/TimePicker/stories/TwentyFour.vue +1 -1
- package/src/components/TimePicker/types.ts +15 -3
- package/src/components/TimePicker/utils.ts +82 -21
- package/src/components/Toast/Toast.md +1 -1
- package/src/components/Toast/Toast.sanitize.test.ts +50 -0
- package/src/components/Toast/Toast.test.ts +5 -0
- package/src/components/Toast/Toast.vue +7 -7
- package/src/components/Toast/ToastProvider.vue +18 -9
- package/src/components/Toast/stories/CustomIcon.vue +1 -1
- package/src/components/Toast/toast.ts +32 -8
- package/src/components/Tooltip/Tooltip.api.md +43 -5
- package/src/components/Tooltip/Tooltip.cy.ts +48 -0
- package/src/components/Tooltip/Tooltip.md +10 -0
- package/src/components/Tooltip/Tooltip.vue +20 -5
- package/src/components/Tooltip/TooltipBubble.vue +2 -2
- package/src/components/Tooltip/TooltipProvider.vue +53 -0
- package/src/components/Tooltip/index.ts +1 -0
- package/src/components/Tooltip/stories/Group.vue +22 -0
- package/src/components/Tooltip/stories/Slots.vue +2 -2
- package/src/components/Tooltip/types.ts +1 -1
- package/src/components/Tree/Tree.api.md +76 -18
- package/src/components/Tree/Tree.md +144 -2
- package/src/components/Tree/Tree.vue +276 -97
- package/src/components/Tree/TreeItem.vue +263 -0
- package/src/components/Tree/index.ts +9 -1
- package/src/components/Tree/stories/DragDrop.vue +94 -0
- package/src/components/Tree/stories/Example.vue +11 -34
- package/src/components/Tree/stories/ExpandAll.vue +48 -0
- package/src/components/Tree/stories/Guides.vue +49 -0
- package/src/components/Tree/stories/ListView.vue +74 -0
- package/src/components/Tree/tree.cy.ts +218 -90
- package/src/components/Tree/types.ts +114 -24
- package/src/components/Tree/useTreeDragDrop.ts +203 -0
- package/src/components/Tree/useTreeKeyboard.ts +109 -0
- package/src/components/VueGridLayout/Layout.vue +1 -1
- package/src/components/shared/picker/PickerShell.vue +20 -15
- package/src/components/shared/popover/PopoverPanel.vue +67 -0
- package/src/components/shared/popover/popoverPanel.css +102 -0
- package/src/components/shared/selection/utils.ts +6 -6
- package/src/composables/useAutofocusOnOpen.ts +2 -0
- package/src/composables/useScreenSize.ts +46 -0
- package/src/composables/useScrollContainer.ts +108 -0
- package/src/composables/useShortcut.ts +3 -0
- package/src/data-fetching/docStore.test.ts +74 -0
- package/src/data-fetching/docStore.ts +18 -7
- package/src/data-fetching/useCall/types.ts +1 -0
- package/src/data-fetching/useCall/useCall.test.ts +43 -0
- package/src/data-fetching/useCall/useCall.ts +17 -4
- package/src/data-fetching/useDoc/useDoc.test.ts +61 -2
- package/src/data-fetching/useDoc/useDoc.ts +35 -15
- package/src/data-fetching/useDoctype/useDoctype.ts +6 -5
- package/src/data-fetching/useFrappeFetch.ts +17 -4
- package/src/data-fetching/useList/types.ts +1 -0
- package/src/data-fetching/useList/useList.test.ts +40 -0
- package/src/data-fetching/useList/useList.ts +20 -13
- package/src/data-fetching/useNewDoc/useNewDoc.ts +9 -5
- package/src/directives/focus.ts +3 -3
- package/src/index.ts +105 -74
- package/src/mocks/handlers.ts +8 -0
- package/src/molecules/editor/Editor.cy.ts +6 -1
- package/src/molecules/editor/EditorBubbleMenu.vue +1 -1
- package/src/molecules/editor/EditorContent.vue +50 -9
- package/src/molecules/editor/EditorFixedMenu.vue +2 -1
- package/src/molecules/editor/EditorFloatingMenu.vue +1 -1
- package/src/molecules/editor/EditorTableMenu.vue +303 -0
- package/src/molecules/editor/MenuItems.vue +81 -69
- package/src/molecules/editor/commands.ts +10 -2
- package/src/molecules/editor/components/AttachmentNodeView.vue +115 -0
- package/src/molecules/editor/components/EditorDropZone.vue +105 -0
- package/src/molecules/editor/components/EditorPopover.vue +89 -0
- package/src/molecules/editor/components/MediaNodeView.vue +156 -49
- package/src/molecules/editor/components/MediaResizeHandles.vue +38 -0
- package/src/molecules/editor/components/MediaToolbar.vue +108 -54
- package/src/molecules/editor/components/TableContextMenu.vue +144 -0
- package/src/molecules/editor/components/UploadProgressIndicator.vue +33 -0
- package/src/molecules/editor/components/VideoControls.vue +208 -0
- package/src/molecules/editor/components/font-color/ColorSwatchGrid.vue +3 -5
- package/src/molecules/editor/components/font-color/fontColorController.ts +28 -23
- package/src/molecules/editor/components/font-color/swatches.ts +1 -1
- package/src/molecules/editor/components/media-node-view-controller.ts +4 -4
- package/src/molecules/editor/components/media-node-view-utils.test.ts +0 -13
- package/src/molecules/editor/components/media-node-view-utils.ts +0 -10
- package/src/molecules/editor/components/table-color/tableCellColorController.ts +80 -0
- package/src/molecules/editor/components/table-size-picker/TableSizePicker.vue +92 -0
- package/src/molecules/editor/components/table-size-picker/tableSizePickerController.ts +40 -0
- package/src/molecules/editor/composables/useEditorFileDrop.ts +117 -0
- package/src/molecules/editor/composables/useFloatingPopup.ts +46 -2
- package/src/molecules/editor/composables/useNodeViewResize.test.ts +60 -11
- package/src/molecules/editor/composables/useNodeViewResize.ts +80 -21
- package/src/molecules/editor/composables/useTableCellColorState.ts +78 -0
- package/src/molecules/editor/composables/useWindowFileDragging.ts +68 -0
- package/src/molecules/editor/extensions/attachment/attachment-engine.ts +250 -0
- package/src/molecules/editor/extensions/attachment/attachment-extension.ts +248 -0
- package/src/molecules/editor/extensions/attachment/attachment.flow.test.ts +80 -0
- package/src/molecules/editor/extensions/attachment/attachment.roundtrip.test.ts +50 -0
- package/src/molecules/editor/extensions/attachment/index.ts +5 -0
- package/src/molecules/editor/extensions/code-block/CodeBlockComponent.css +16 -26
- package/src/molecules/editor/extensions/code-block/CodeBlockComponent.vue +107 -22
- package/src/molecules/editor/extensions/content-paste/content-paste-extension.ts +5 -3
- package/src/molecules/editor/extensions/iframe/IframeInsertDialog.vue +34 -7
- package/src/molecules/editor/extensions/iframe/IframeNodeView.vue +54 -48
- package/src/molecules/editor/extensions/iframe/iframe-allowlist.ts +33 -4
- package/src/molecules/editor/extensions/iframe/iframe-commands.ts +49 -5
- package/src/molecules/editor/extensions/iframe/iframe-embed-utils.ts +30 -0
- package/src/molecules/editor/extensions/iframe/iframe-extension.ts +4 -4
- package/src/molecules/editor/extensions/iframe/iframeInsertDialogController.ts +12 -1
- package/src/molecules/editor/extensions/iframe/index.ts +4 -4
- package/src/molecules/editor/extensions/iframe/useIframeDialog.ts +25 -13
- package/src/molecules/editor/extensions/image/image-extension.ts +29 -11
- package/src/molecules/editor/extensions/image-group/ImageGroupGrid.vue +27 -11
- package/src/molecules/editor/extensions/image-group/ImageGroupGridCell.vue +55 -11
- package/src/molecules/editor/extensions/image-group/ImageGroupNodeView.vue +64 -31
- package/src/molecules/editor/extensions/image-group/ImageGroupUploadDialog.vue +84 -40
- package/src/molecules/editor/extensions/image-group/image-group-extension.ts +4 -3
- package/src/molecules/editor/extensions/image-group/useImageGroupDialog.ts +116 -17
- package/src/molecules/editor/extensions/link/LinkEditorPopup.vue +214 -71
- package/src/molecules/editor/extensions/link/link-click-plugin.ts +10 -15
- package/src/molecules/editor/extensions/link/link-commands.ts +24 -3
- package/src/molecules/editor/extensions/link/link-extension.ts +11 -2
- package/src/molecules/editor/extensions/link/link-popup-controller.test.ts +49 -0
- package/src/molecules/editor/extensions/link/link-popup-controller.ts +67 -2
- package/src/molecules/editor/extensions/link/link-shortcut-plugin.ts +7 -2
- package/src/molecules/editor/extensions/media-drop/media-drop-extension.ts +177 -0
- package/src/molecules/editor/extensions/shared/media-dimensions.ts +36 -3
- package/src/molecules/editor/extensions/shared/media-node-ops.ts +17 -0
- package/src/molecules/editor/extensions/shared/media-plugin.test.ts +60 -0
- package/src/molecules/editor/extensions/shared/media-plugin.ts +7 -37
- package/src/molecules/editor/extensions/shared/media-upload-engine.test.ts +39 -2
- package/src/molecules/editor/extensions/shared/media-upload-engine.ts +104 -10
- package/src/molecules/editor/extensions/shared/media-upload-state.ts +55 -0
- package/src/molecules/editor/extensions/shared/media-upload-types.ts +52 -1
- package/src/molecules/editor/extensions/shared/suggestion-helpers.ts +20 -0
- package/src/molecules/editor/extensions/shared/suggestion-types.ts +7 -0
- package/src/molecules/editor/extensions/shared/upload-types.ts +1 -0
- package/src/molecules/editor/extensions/slash-commands/slash-commands-extension.test.ts +38 -0
- package/src/molecules/editor/extensions/slash-commands/slash-commands-extension.ts +119 -55
- package/src/molecules/editor/extensions/suggestion/SuggestionList.vue +62 -22
- package/src/molecules/editor/extensions/suggestion/SuggestionListItem.vue +1 -1
- package/src/molecules/editor/extensions/suggestion/createSuggestionExtension.ts +4 -0
- package/src/molecules/editor/extensions/table/drag-scroll.ts +154 -0
- package/src/molecules/editor/extensions/table/table-cell-color.ts +188 -0
- package/src/molecules/editor/extensions/table/table-navigation.ts +560 -0
- package/src/molecules/editor/extensions/table/table-selection-overlay.ts +137 -0
- package/src/molecules/editor/extensions/toc-node/TocNodeView.vue +1 -1
- package/src/molecules/editor/extensions/toc-node/toc-render.ts +7 -3
- package/src/molecules/editor/extensions/video/video-extension.ts +72 -5
- package/src/molecules/editor/extensions.ts +176 -8
- package/src/molecules/editor/index.ts +9 -4
- package/src/molecules/editor/kits.test.ts +21 -1
- package/src/molecules/editor/kits.ts +56 -33
- package/src/molecules/editor/menu.test.ts +3 -1
- package/src/molecules/editor/menu.ts +180 -18
- package/src/molecules/editor/stories/Comment.vue +4 -4
- package/src/molecules/editor/stories/Inline.vue +1 -1
- package/src/molecules/editor/stories/Primitives.vue +1 -1
- package/src/molecules/editor/stories/RichText.vue +1 -1
- package/src/molecules/editor/style.css +80 -3
- package/src/molecules/editor/useEditor.test.ts +4 -0
- package/src/molecules/editor/useEditor.ts +7 -3
- package/src/molecules/list/List.cy.ts +626 -0
- package/src/molecules/list/List.vue +93 -0
- package/src/molecules/list/ListCell.vue +15 -0
- package/src/molecules/list/ListGroup.vue +40 -0
- package/src/molecules/list/ListHeader.vue +62 -0
- package/src/molecules/list/ListHeaderCell.vue +26 -0
- package/src/molecules/list/ListHeaderCellSort.vue +106 -0
- package/src/molecules/list/ListRow.vue +55 -0
- package/src/molecules/list/ListRowBase.vue +103 -0
- package/src/molecules/list/ListRows.vue +120 -0
- package/src/molecules/list/index.ts +24 -0
- package/src/molecules/list/list-context.ts +44 -0
- package/src/molecules/list/list.api.md +276 -0
- package/src/molecules/list/list.md +119 -0
- package/src/molecules/list/stories/Columns.vue +103 -0
- package/src/molecules/list/stories/Feed.vue +105 -0
- package/src/molecules/list/stories/Virtual.vue +31 -0
- package/src/molecules/list/style.css +173 -0
- package/src/molecules/list/types.ts +82 -0
- package/src/molecules/list/useVirtualRows.ts +80 -0
- package/src/resources/documentResource.d.ts +28 -0
- package/src/resources/documentResource.js +32 -4
- package/src/resources/documentResource.test.ts +111 -0
- package/src/resources/listResource.d.ts +33 -0
- package/src/resources/plugin.d.ts +7 -0
- package/src/resources/resources.d.ts +35 -0
- package/src/utils/{call.js → call.ts} +50 -9
- package/src/utils/config.ts +16 -1
- package/src/utils/confirmDialog.d.ts +17 -0
- package/src/utils/debounce.ts +6 -7
- package/src/utils/dialog.cy.ts +9 -9
- package/src/utils/fileSize.ts +36 -0
- package/src/utils/fileUploadHandler.ts +46 -6
- package/src/utils/frappeRequest.test.ts +79 -0
- package/src/utils/{frappeRequest.js → frappeRequest.ts} +76 -13
- package/src/utils/pageMeta.ts +1 -1
- package/src/utils/plugin.ts +58 -0
- package/src/utils/{request.js → request.ts} +28 -3
- package/src/utils/{socketio.js → socketio.ts} +11 -1
- package/src/utils/theme.ts +48 -57
- package/src/utils/useFileUpload.ts +80 -23
- package/tailwind/audit-token-drift.cjs +176 -0
- package/tailwind/colorPalette.js +69 -8
- package/tailwind/colors.json +1115 -397
- package/tailwind/figma-tokens-to-theme.js +364 -0
- package/tailwind/generated/colors.json +1217 -0
- package/tailwind/generated/effects.json +41 -0
- package/tailwind/generated/radius.json +20 -0
- package/tailwind/generated/typography.json +479 -0
- package/tailwind/migrate-tokens-v2.js +453 -0
- package/tailwind/migrate-tokens-v2.test.js +55 -0
- package/tailwind/plugin.js +220 -15
- package/tailwind/preset.js +15 -0
- package/tailwind/tokens.js +35 -37
- package/tsconfig.base.json +2 -2
- package/vitepress/components/Docs/CommandPalette.vue +214 -0
- package/vitepress/components/Docs/Demo.vue +60 -0
- package/vitepress/components/Docs/EmitsTable.vue +99 -0
- package/vitepress/components/Docs/MobileNavSheet.vue +148 -0
- package/vitepress/components/Docs/OnThisPage.vue +74 -0
- package/vitepress/components/Docs/PrevNextBtns.vue +58 -0
- package/vitepress/components/Docs/PropsTable.vue +185 -0
- package/vitepress/components/Docs/Search.vue +34 -0
- package/vitepress/components/Docs/Sidebar.vue +91 -0
- package/vitepress/components/Docs/SlotsTable.vue +99 -0
- package/vitepress/components/Docs/index.ts +13 -0
- package/vitepress/components/Docs/sidebarList.ts +33 -0
- package/vitepress/components/Layout.vue +58 -0
- package/vitepress/components/Navbar.vue +126 -0
- package/vitepress/components/index.ts +3 -0
- package/vitepress/composables/index.ts +3 -0
- package/vitepress/composables/useTheme.ts +39 -0
- package/vitepress/css/fonts/Inter-Italic.var.woff2 +0 -0
- package/vitepress/css/fonts/Inter.var.woff2 +0 -0
- package/vitepress/css/style.css +198 -0
- package/vitepress/index.d.ts +23 -0
- package/vitepress/index.node.ts +175 -0
- package/vitepress/index.ts +17 -0
- package/vitepress/plugins/colocatedComponentDocs.ts +164 -0
- package/vitepress/plugins/componentTransformer.ts +286 -0
- package/vitepress/plugins/index.ts +12 -0
- package/vitepress/state.ts +10 -0
- package/vitepress/theme/index.ts +21 -0
- package/frappe/telemetry/utils.ts +0 -15
- package/src/components/Badge/stories/Themes.vue +0 -10
- package/src/components/Badge/stories/Variants.vue +0 -10
- package/src/components/Button/stories/Icons.vue +0 -27
- package/src/components/Button/stories/Sizes.vue +0 -11
- package/src/components/Button/stories/Themes.vue +0 -10
- package/src/components/Button/stories/Variants.vue +0 -10
- package/src/components/Popover/stories/Hover.vue +0 -14
- package/src/components/Resource.vue +0 -21
- package/src/components/Sidebar/stories/Example.vue +0 -76
- package/src/components/Spinner.vue +0 -3
- package/src/components/TabButtons/TabButtons.story.vue +0 -22
- package/src/utils/plugin.js +0 -24
- /package/src/components/Dropdown/stories/{02_Shortcuts.vue → Shortcuts.vue} +0 -0
- /package/src/components/Dropdown/stories/{01_Simple.vue → Simple.vue} +0 -0
- /package/src/components/Dropdown/stories/{03_Submenus.vue → Submenus.vue} +0 -0
- /package/src/components/Dropdown/stories/{04_Switches.vue → Switches.vue} +0 -0
- /package/src/components/{Dropdown/DropdownRenderContentAsChild.vue → Menu/MenuRenderContentAsChild.vue} +0 -0
package/tailwind/plugin.js
CHANGED
|
@@ -3,12 +3,158 @@ import {
|
|
|
3
3
|
generateColorPalette,
|
|
4
4
|
generateSemanticColors,
|
|
5
5
|
generateCSSVariables,
|
|
6
|
+
generateEffectVariables,
|
|
6
7
|
} from './colorPalette.js'
|
|
7
|
-
import
|
|
8
|
+
import radiusTokens from './generated/radius.json'
|
|
9
|
+
import typographyTokens from './generated/typography.json'
|
|
10
|
+
import effectsData from './generated/effects.json'
|
|
8
11
|
|
|
9
12
|
let colorPalette = generateColorPalette()
|
|
10
13
|
let semanticColors = generateSemanticColors()
|
|
11
|
-
let cssVariables =
|
|
14
|
+
let cssVariables = mergeVariableLayers(
|
|
15
|
+
generateCSSVariables(),
|
|
16
|
+
generateEffectVariables(),
|
|
17
|
+
generateRadiusVariables(),
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
// Emit `--radius-{key}` for every radius token (numeric scale + aliases) so
|
|
21
|
+
// the values are inspectable as real CSS variables. `borderRadius` is rewired
|
|
22
|
+
// below to consume these vars, so `rounded-4` and `--radius-4` stay in sync.
|
|
23
|
+
function generateRadiusVariables() {
|
|
24
|
+
const vars = {}
|
|
25
|
+
for (const [key, value] of Object.entries(radiusTokens)) {
|
|
26
|
+
if (key === 'DEFAULT') continue
|
|
27
|
+
vars[`--radius-${key}`] = value
|
|
28
|
+
}
|
|
29
|
+
return { ':root': vars }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Map `DEFAULT` (Tailwind's `rounded` class) onto the numeric var that
|
|
33
|
+
// shares its value, so we don't emit a `--radius-DEFAULT` (awkward name).
|
|
34
|
+
// Each value carries a trailing `/* {px} */` comment so editor tooling
|
|
35
|
+
// (Tailwind IntelliSense) surfaces the resolved px on hover, instead of
|
|
36
|
+
// the opaque `var(--radius-*)` reference.
|
|
37
|
+
function buildRadiusConfig() {
|
|
38
|
+
const numericByValue = {}
|
|
39
|
+
for (const [key, value] of Object.entries(radiusTokens)) {
|
|
40
|
+
if (/^\d+$/.test(key)) numericByValue[value] = key
|
|
41
|
+
}
|
|
42
|
+
const out = {}
|
|
43
|
+
for (const [key, value] of Object.entries(radiusTokens)) {
|
|
44
|
+
if (key === 'DEFAULT') {
|
|
45
|
+
const numeric = numericByValue[value]
|
|
46
|
+
out[key] = numeric ? `var(--radius-${numeric}) /* ${value} */` : value
|
|
47
|
+
} else {
|
|
48
|
+
out[key] = `var(--radius-${key}) /* ${value} */`
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return out
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Merge two `{ selector: { var: value } }` objects into one, preserving any
|
|
55
|
+
// vars already declared under the same selector.
|
|
56
|
+
function mergeVariableLayers(...layers) {
|
|
57
|
+
const out = {}
|
|
58
|
+
for (const layer of layers) {
|
|
59
|
+
for (const [selector, vars] of Object.entries(layer)) {
|
|
60
|
+
out[selector] = { ...(out[selector] || {}), ...vars }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return out
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Weight variants are exposed as component classes — `text-<size>-<weight>` and
|
|
67
|
+
// the paragraph counterpart `text-p-<size>-<weight>` — one per Figma named
|
|
68
|
+
// style. Figma tracks each weight differently per size and CSS letter-spacing
|
|
69
|
+
// can't follow font-weight, so each (size, weight) must ship as a self-contained
|
|
70
|
+
// class. `regular` stays the bare `text-<size>` / `text-p-<size>` utility.
|
|
71
|
+
// (Component classes are JIT-purged, so only the ones used in content emit.)
|
|
72
|
+
const WEIGHT_VARIANTS = ['medium', 'semibold', 'bold', 'black']
|
|
73
|
+
|
|
74
|
+
function buildFontSize() {
|
|
75
|
+
const out = {}
|
|
76
|
+
// Each size's regular variant already carries lineHeight, letterSpacing and
|
|
77
|
+
// fontWeight from the text-styles export (see figma-tokens-to-theme.js).
|
|
78
|
+
for (const [key, [size, meta]] of Object.entries(typographyTokens.fontSize)) {
|
|
79
|
+
out[key] = [size, { ...meta }]
|
|
80
|
+
}
|
|
81
|
+
// Paragraph variants (`text-p-<size>`): same size, the paragraph style's
|
|
82
|
+
// looser line-height and its own letter-spacing.
|
|
83
|
+
for (const [key, p] of Object.entries(typographyTokens.paragraph || {})) {
|
|
84
|
+
if (!out[key]) continue
|
|
85
|
+
const [size, meta] = out[key]
|
|
86
|
+
out[`p-${key}`] = [
|
|
87
|
+
size,
|
|
88
|
+
{ ...meta, lineHeight: p.lineHeight, letterSpacing: p.letterSpacing },
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
return out
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Focus ring utilities backed by `--focus-outline-*` CSS vars (theme-flipped
|
|
95
|
+
// in colorPalette.js#generateEffectVariables). Implemented as `outline`, not
|
|
96
|
+
// box-shadow, so rings never collide with shadow/ring utilities on the same
|
|
97
|
+
// element and survive forced-colors mode. The default ring is applied
|
|
98
|
+
// globally via `:focus-visible` (see globalStyles); these utilities are for
|
|
99
|
+
// themed overrides (`focus-visible:focus-ring-red`) and non-focus states
|
|
100
|
+
// (`data-[state=open]:focus-ring`). Registered via `addComponents` so
|
|
101
|
+
// Tailwind IntelliSense picks them up.
|
|
102
|
+
function buildFocusRingUtilities() {
|
|
103
|
+
const out = {}
|
|
104
|
+
for (const name of Object.keys(effectsData.focus.light)) {
|
|
105
|
+
const className = name === 'default' ? '.focus-ring' : `.focus-ring-${name}`
|
|
106
|
+
out[className] = {
|
|
107
|
+
outline: `var(--focus-outline-${name})`,
|
|
108
|
+
outlineOffset: '0px',
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return out
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function buildTextStyleUtilities() {
|
|
115
|
+
const out = {}
|
|
116
|
+
const t = typographyTokens
|
|
117
|
+
const groups = [
|
|
118
|
+
{
|
|
119
|
+
className: (s, w) => `.text-${s}-${w}`,
|
|
120
|
+
tracking: t.tracking?.text || {},
|
|
121
|
+
lineHeight: (s) => t.fontSize[s]?.[1].lineHeight,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
className: (s, w) => `.text-p-${s}-${w}`,
|
|
125
|
+
tracking: t.tracking?.paragraph || {},
|
|
126
|
+
lineHeight: (s) => t.paragraph?.[s]?.lineHeight,
|
|
127
|
+
},
|
|
128
|
+
]
|
|
129
|
+
for (const group of groups) {
|
|
130
|
+
for (const [size, byWeight] of Object.entries(group.tracking)) {
|
|
131
|
+
const entry = t.fontSize[size]
|
|
132
|
+
if (!entry) continue
|
|
133
|
+
const [fontSize] = entry
|
|
134
|
+
const lineHeight = group.lineHeight(size)
|
|
135
|
+
const transform = t.textTransform?.[size]
|
|
136
|
+
for (const weight of WEIGHT_VARIANTS) {
|
|
137
|
+
if (!(weight in byWeight)) continue
|
|
138
|
+
out[group.className(size, weight)] = {
|
|
139
|
+
fontSize,
|
|
140
|
+
lineHeight,
|
|
141
|
+
fontWeight: String(t.fontWeight[weight]),
|
|
142
|
+
letterSpacing: byWeight[weight],
|
|
143
|
+
...(transform ? { textTransform: transform } : {}),
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// `tiny` is an uppercase eyebrow style; the bare regular utility needs the
|
|
149
|
+
// text-transform too (Tailwind's fontSize tuple can't express it).
|
|
150
|
+
for (const [size, transform] of Object.entries(t.textTransform || {})) {
|
|
151
|
+
out[`.text-${size}`] = {
|
|
152
|
+
...(out[`.text-${size}`] || {}),
|
|
153
|
+
textTransform: transform,
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return out
|
|
157
|
+
}
|
|
12
158
|
|
|
13
159
|
let globalStyles = (theme) => ({
|
|
14
160
|
html: {
|
|
@@ -26,41 +172,81 @@ let globalStyles = (theme) => ({
|
|
|
26
172
|
backgroundSize: '1.13em',
|
|
27
173
|
backgroundPosition: 'right 0.44rem center',
|
|
28
174
|
},
|
|
175
|
+
// A bare `<p>` reads as body copy, so it defaults to a relaxed line-height
|
|
176
|
+
// instead of the tight value baked into the `text-<size>` utilities. Kept at
|
|
177
|
+
// element specificity (0,0,1) with `:where()` (which adds none) so any explicit
|
|
178
|
+
// `text-*` / `text-p-*` line-height wins, and scoped out of rich text so the
|
|
179
|
+
// `prose` / editor line-heights are untouched.
|
|
180
|
+
'p:not(:where(.prose, .ProseMirror) *)': {
|
|
181
|
+
lineHeight: '1.5',
|
|
182
|
+
},
|
|
183
|
+
// Global keyboard focus indicator (espresso v2 focus/default token).
|
|
184
|
+
// Lives in the base layer so any utility on the element can override it:
|
|
185
|
+
// suppress with `focus-visible:outline-none`, retheme with
|
|
186
|
+
// `focus-visible:focus-ring-<color>`.
|
|
187
|
+
':focus-visible': {
|
|
188
|
+
outline: 'var(--focus-outline-default)',
|
|
189
|
+
outlineOffset: '0px',
|
|
190
|
+
},
|
|
29
191
|
})
|
|
30
192
|
|
|
31
193
|
let componentStyles = {
|
|
32
194
|
'.form-input, .form-textarea, .form-select': {
|
|
33
|
-
'@apply h-7 rounded border border-[--surface-gray-2] bg-surface-gray-2 py-1.5 pl-2 pr-2 text-base text-ink-gray-8 placeholder-ink-gray-4 transition-colors hover:border-outline-
|
|
195
|
+
'@apply h-7 rounded border border-[--surface-gray-2] bg-surface-gray-2 py-1.5 pl-2 pr-2 text-base text-ink-gray-8 placeholder-ink-gray-4 transition-colors hover:border-outline-elevation-2 hover:bg-surface-gray-3 focus:border-outline-gray-4 focus:bg-surface-base focus:shadow-sm focus:ring-0':
|
|
34
196
|
{},
|
|
35
197
|
},
|
|
36
198
|
'.form-checkbox': {
|
|
37
|
-
'@apply rounded-md bg-surface-gray-2 text-ink-blue-
|
|
38
|
-
{},
|
|
199
|
+
'@apply rounded-md bg-surface-gray-2 text-ink-blue-5 focus:ring-0': {},
|
|
39
200
|
},
|
|
40
201
|
"[data-theme='dark'] [type='checkbox']:checked": {
|
|
41
202
|
'background-image': `url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='%230F0F0F' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")`,
|
|
42
203
|
},
|
|
43
|
-
"[data-theme='dark'] img": {
|
|
44
|
-
filter: 'brightness(.8) contrast(1.2)',
|
|
45
|
-
},
|
|
46
204
|
}
|
|
47
205
|
|
|
48
206
|
export default plugin(
|
|
49
|
-
function ({ addBase, addComponents, theme }) {
|
|
207
|
+
function ({ addBase, addComponents, matchUtilities, theme }) {
|
|
50
208
|
addBase({ ...globalStyles(theme), ...cssVariables })
|
|
51
209
|
addComponents(componentStyles)
|
|
210
|
+
addComponents(buildTextStyleUtilities())
|
|
211
|
+
addComponents(buildFocusRingUtilities())
|
|
212
|
+
// Authoring sugar for the list-family styling hooks (frappe-ui/list),
|
|
213
|
+
// on the spacing scale with variants and arbitrary values:
|
|
214
|
+
// `max-sm:list-gap-3` instead of `max-sm:[--list-gap:0.75rem]`.
|
|
215
|
+
matchUtilities(
|
|
216
|
+
{
|
|
217
|
+
'list-gap': (value) => ({ '--list-gap': value }),
|
|
218
|
+
'list-row-px': (value) => ({ '--list-row-padding-x': value }),
|
|
219
|
+
},
|
|
220
|
+
{ values: theme('spacing') },
|
|
221
|
+
)
|
|
222
|
+
// Grid tracks are arbitrary-only (no meaningful scale):
|
|
223
|
+
// `max-md:list-cols-[minmax(0,1fr)_auto]` instead of
|
|
224
|
+
// `max-md:[--list-columns:minmax(0,1fr)_auto]`.
|
|
225
|
+
matchUtilities({
|
|
226
|
+
'list-cols': (value) => ({ '--list-columns': value }),
|
|
227
|
+
})
|
|
52
228
|
},
|
|
53
229
|
{
|
|
54
230
|
theme: {
|
|
55
231
|
colors: colorPalette,
|
|
56
|
-
borderRadius:
|
|
57
|
-
boxShadow:
|
|
232
|
+
borderRadius: buildRadiusConfig(),
|
|
233
|
+
boxShadow: {
|
|
234
|
+
none: 'none',
|
|
235
|
+
sm: 'var(--elevation-sm)',
|
|
236
|
+
base: 'var(--elevation-base)',
|
|
237
|
+
DEFAULT: 'var(--elevation-base)',
|
|
238
|
+
md: 'var(--elevation-md)',
|
|
239
|
+
lg: 'var(--elevation-lg)',
|
|
240
|
+
xl: 'var(--elevation-xl)',
|
|
241
|
+
'2xl': 'var(--elevation-2xl)',
|
|
242
|
+
status: 'var(--elevation-status)',
|
|
243
|
+
},
|
|
58
244
|
container: {
|
|
59
245
|
padding: {
|
|
60
246
|
xl: '5rem',
|
|
61
247
|
},
|
|
62
248
|
},
|
|
63
|
-
fontSize:
|
|
249
|
+
fontSize: buildFontSize(),
|
|
64
250
|
screens: {
|
|
65
251
|
sm: '640px',
|
|
66
252
|
md: '768px',
|
|
@@ -73,11 +259,14 @@ export default plugin(
|
|
|
73
259
|
},
|
|
74
260
|
backgroundColor: {
|
|
75
261
|
surface: semanticColors.surface,
|
|
262
|
+
'surface-alpha': semanticColors['surface-alpha'],
|
|
76
263
|
},
|
|
77
264
|
gradientColorStops: {
|
|
78
265
|
surface: semanticColors.surface,
|
|
266
|
+
'surface-alpha': semanticColors['surface-alpha'],
|
|
79
267
|
ink: semanticColors.ink,
|
|
80
268
|
outline: semanticColors.outline,
|
|
269
|
+
'outline-alpha': semanticColors['outline-alpha'],
|
|
81
270
|
},
|
|
82
271
|
fill: {
|
|
83
272
|
ink: semanticColors.ink,
|
|
@@ -92,12 +281,15 @@ export default plugin(
|
|
|
92
281
|
borderColor: () => ({
|
|
93
282
|
DEFAULT: 'var(--outline-gray-1)',
|
|
94
283
|
outline: semanticColors.outline,
|
|
284
|
+
'outline-alpha': semanticColors['outline-alpha'],
|
|
95
285
|
}),
|
|
96
286
|
ringColor: {
|
|
97
287
|
outline: semanticColors.outline,
|
|
288
|
+
'outline-alpha': semanticColors['outline-alpha'],
|
|
98
289
|
},
|
|
99
290
|
divideColor: {
|
|
100
291
|
outline: semanticColors.outline,
|
|
292
|
+
'outline-alpha': semanticColors['outline-alpha'],
|
|
101
293
|
},
|
|
102
294
|
spacing: {
|
|
103
295
|
4.5: '1.125rem',
|
|
@@ -260,7 +452,7 @@ export default plugin(
|
|
|
260
452
|
v3: {
|
|
261
453
|
css: [
|
|
262
454
|
{
|
|
263
|
-
fontSize: 'var(--prose-font-size,
|
|
455
|
+
fontSize: 'var(--prose-font-size, 15px)',
|
|
264
456
|
fontWeight: 420,
|
|
265
457
|
lineHeight: '1.7',
|
|
266
458
|
letterSpacing: '0.02em',
|
|
@@ -276,13 +468,26 @@ export default plugin(
|
|
|
276
468
|
// links: subtle bottom border, darkens on hover
|
|
277
469
|
a: {
|
|
278
470
|
textDecoration: 'none',
|
|
279
|
-
borderBottom: '1px solid var(--ink-gray-
|
|
471
|
+
borderBottom: '1px solid var(--ink-gray-4)',
|
|
280
472
|
transition: 'border-color 0.08s ease',
|
|
281
473
|
},
|
|
282
474
|
'a:hover': {
|
|
283
475
|
borderBottom: '1px solid var(--ink-gray-6)',
|
|
284
476
|
},
|
|
285
477
|
|
|
478
|
+
// named text color + bold: the color lives on a `textStyle`
|
|
479
|
+
// span that wraps (or is wrapped by) `<strong>`. Typography's
|
|
480
|
+
// `strong { color: var(--tw-prose-bold) }` otherwise overrides
|
|
481
|
+
// the inherited named color, painting bold text gray. Mirror the
|
|
482
|
+
// base preset's `a strong { color: inherit }` so bold keeps the
|
|
483
|
+
// span's color in both nesting orders.
|
|
484
|
+
':where(span[style*="--prose-color-"]) strong': {
|
|
485
|
+
color: 'inherit',
|
|
486
|
+
},
|
|
487
|
+
'strong:where([style*="--prose-color-"])': {
|
|
488
|
+
color: 'inherit',
|
|
489
|
+
},
|
|
490
|
+
|
|
286
491
|
// inline code: subtle pill — strip Tailwind's added quotes
|
|
287
492
|
'code::before': { content: 'none' },
|
|
288
493
|
'code::after': { content: 'none' },
|
|
@@ -380,7 +585,7 @@ export default plugin(
|
|
|
380
585
|
ol: {
|
|
381
586
|
marginTop: '4px',
|
|
382
587
|
marginBottom: '4px',
|
|
383
|
-
paddingInlineStart: '1.
|
|
588
|
+
paddingInlineStart: '1.7em',
|
|
384
589
|
},
|
|
385
590
|
li: {
|
|
386
591
|
marginTop: '4px',
|
package/tailwind/preset.js
CHANGED
|
@@ -7,9 +7,24 @@ import lucideIconsPlugin from './lucideIconsPlugin.js'
|
|
|
7
7
|
// config (it reads only the top-level config's content.files). So consuming
|
|
8
8
|
// apps must list frappe-ui's source globs in their own tailwind.config
|
|
9
9
|
// `content` — declaring them here would be silently ignored.
|
|
10
|
+
// Stock Tailwind's numeric spacing scale has gaps above 12 (13, 15, 17, 18,
|
|
11
|
+
// 19, 21… are undefined), so `h-17` / `size-17` silently don't compile. Fill
|
|
12
|
+
// every integer 1–64 at the canonical 0.25rem step. Values match Tailwind's own
|
|
13
|
+
// formula, so overriding the already-defined keys is a no-op; the win is the
|
|
14
|
+
// in-between steps. Presets DO merge `theme` (unlike `content`), so this reaches
|
|
15
|
+
// consuming apps automatically.
|
|
16
|
+
const integerSpacing = Object.fromEntries(
|
|
17
|
+
Array.from({ length: 64 }, (_, i) => i + 1).map((n) => [n, `${n * 0.25}rem`]),
|
|
18
|
+
)
|
|
19
|
+
|
|
10
20
|
/** @type {import('tailwindcss').Config} */
|
|
11
21
|
export default {
|
|
12
22
|
darkMode: ['selector', '[data-theme="dark"]'],
|
|
23
|
+
theme: {
|
|
24
|
+
extend: {
|
|
25
|
+
spacing: integerSpacing,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
13
28
|
// The editor applies `prose prose-v3` via a computed string in EditorContent,
|
|
14
29
|
// which the JIT scanner can miss (HMR rebuilds, or a consumer that didn't add
|
|
15
30
|
// the molecules glob to `content`) — then prose-v3 typography silently drops.
|
package/tailwind/tokens.js
CHANGED
|
@@ -1,45 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
1
|
+
// Public token exports for external consumers (Tailwind v3 presets, CSS-in-JS,
|
|
2
|
+
// design-system tooling). Sourced from the Figma-synced `./generated/*` JSON;
|
|
3
|
+
// the plugin reads the same generated files directly so both stay in sync via
|
|
4
|
+
// `yarn sync-tokens`.
|
|
5
|
+
import radiusTokens from './generated/radius.json'
|
|
6
|
+
import typographyTokens from './generated/typography.json'
|
|
7
|
+
import effectsData from './generated/effects.json'
|
|
8
|
+
|
|
9
|
+
const borderRadius = radiusTokens
|
|
11
10
|
|
|
11
|
+
// Elevation tokens are flipped per theme by the plugin via CSS vars; the
|
|
12
|
+
// exported shape keeps static values so non-runtime consumers (snapshot tests,
|
|
13
|
+
// docs tooling) still get sensible defaults.
|
|
12
14
|
const boxShadow = {
|
|
13
|
-
sm: '0px 1px 2px rgba(0, 0, 0, 0.1)',
|
|
14
|
-
DEFAULT:
|
|
15
|
-
'0px 0px 1px rgba(0, 0, 0, 0.45), 0px 1px 2px rgba(0, 0, 0, 0.1)',
|
|
16
|
-
md: '0px 0px 1px rgba(0, 0, 0, 0.12), 0px 0.5px 2px rgba(0, 0, 0, 0.15), 0px 2px 3px rgba(0, 0, 0, 0.16)',
|
|
17
|
-
lg: '0px 0px 1px rgba(0, 0, 0, 0.35), 0px 6px 8px -4px rgba(0, 0, 0, 0.1)',
|
|
18
|
-
xl: '0px 0px 1px rgba(0, 0, 0, 0.19), 0px 1px 2px rgba(0, 0, 0, 0.07), 0px 6px 15px -5px rgba(0, 0, 0, 0.11)',
|
|
19
|
-
'2xl':
|
|
20
|
-
'0px 0px 1px rgba(0, 0, 0, 0.2), 0px 1px 3px rgba(0, 0, 0, 0.05), 0px 10px 24px -3px rgba(0, 0, 0, 0.1)',
|
|
21
15
|
none: 'none',
|
|
16
|
+
...effectsData.elevation.light,
|
|
17
|
+
DEFAULT: effectsData.elevation.light.base,
|
|
18
|
+
...effectsData.elevation.custom,
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
'p-3xl': ['24px', { lineHeight: '1.2', fontWeight: 400, letterSpacing: '0.005em' }],
|
|
21
|
+
// lineHeight, letterSpacing and fontWeight are baked into each size tuple by
|
|
22
|
+
// the token sync (see figma-tokens-to-theme.js#buildTypography); mirror the
|
|
23
|
+
// plugin's `buildFontSize` so this public export stays in sync.
|
|
24
|
+
function buildFontSize() {
|
|
25
|
+
const out = {}
|
|
26
|
+
for (const [key, [size, meta]] of Object.entries(typographyTokens.fontSize)) {
|
|
27
|
+
out[key] = [size, { ...meta }]
|
|
28
|
+
}
|
|
29
|
+
for (const [key, p] of Object.entries(typographyTokens.paragraph || {})) {
|
|
30
|
+
if (!out[key]) continue
|
|
31
|
+
const [size, meta] = out[key]
|
|
32
|
+
out[`p-${key}`] = [
|
|
33
|
+
size,
|
|
34
|
+
{ ...meta, lineHeight: p.lineHeight, letterSpacing: p.letterSpacing },
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
return out
|
|
42
38
|
}
|
|
43
39
|
|
|
40
|
+
const fontSize = buildFontSize()
|
|
41
|
+
|
|
44
42
|
export { borderRadius, boxShadow, fontSize }
|
|
45
|
-
export * from
|
|
43
|
+
export * from './colorPalette.js'
|
package/tsconfig.base.json
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"lib": ["ESNext", "DOM"],
|
|
14
14
|
"skipLibCheck": true,
|
|
15
15
|
"noEmit": true,
|
|
16
|
-
"types": ["vitest/globals", "unplugin-icons/types/vue"],
|
|
16
|
+
"types": ["vitest/globals", "unplugin-icons/types/vue", "node"],
|
|
17
17
|
"declaration": true,
|
|
18
|
-
"emitDeclarationOnly": true
|
|
18
|
+
"emitDeclarationOnly": true
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useData, useRouter, withBase } from 'vitepress'
|
|
3
|
+
import { computed, ref, watch } from 'vue'
|
|
4
|
+
import fuzzysort from 'fuzzysort'
|
|
5
|
+
import {
|
|
6
|
+
ListboxContent,
|
|
7
|
+
ListboxFilter,
|
|
8
|
+
ListboxGroup,
|
|
9
|
+
ListboxGroupLabel,
|
|
10
|
+
ListboxItem,
|
|
11
|
+
ListboxRoot,
|
|
12
|
+
} from 'reka-ui'
|
|
13
|
+
|
|
14
|
+
import { Dialog } from 'frappe-ui'
|
|
15
|
+
import type { SidebarItem } from './sidebarList'
|
|
16
|
+
|
|
17
|
+
const open = defineModel<boolean>('open', { default: true })
|
|
18
|
+
|
|
19
|
+
const { theme } = useData()
|
|
20
|
+
const router = useRouter()
|
|
21
|
+
|
|
22
|
+
const filterText = ref('')
|
|
23
|
+
|
|
24
|
+
// Sidebar is supplied via themeConfig in the {text, items:[{text,link}]} shape.
|
|
25
|
+
const sidebarList = theme.value.sidebar ?? []
|
|
26
|
+
const allItems = sidebarList.flatMap((section) =>
|
|
27
|
+
section.items.map((item) => ({ ...item, section: section.text })),
|
|
28
|
+
)
|
|
29
|
+
const sectionOrder = sidebarList.map((s) => s.text)
|
|
30
|
+
|
|
31
|
+
watch(open, (isOpen) => {
|
|
32
|
+
if (!isOpen) filterText.value = ''
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const groupedResults = computed(() => {
|
|
36
|
+
const query = filterText.value.trim()
|
|
37
|
+
if (!query) return sidebarList
|
|
38
|
+
|
|
39
|
+
const matches = fuzzysort.go(query, allItems, {
|
|
40
|
+
key: 'text',
|
|
41
|
+
threshold: 0.3,
|
|
42
|
+
limit: 50,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const bySection = new Map<string, SidebarItem[]>()
|
|
46
|
+
for (const m of matches) {
|
|
47
|
+
const item = m.obj
|
|
48
|
+
if (!bySection.has(item.section)) bySection.set(item.section, [])
|
|
49
|
+
bySection.get(item.section)!.push(item)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return sectionOrder
|
|
53
|
+
.filter((name) => bySection.has(name))
|
|
54
|
+
.map((name) => ({ text: name, items: bySection.get(name)! }))
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const hasResults = computed(() =>
|
|
58
|
+
groupedResults.value.some((g) => g.items.length > 0),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const highlightedLink = ref<string | null>(null)
|
|
62
|
+
const onHighlight = (payload: { value: unknown } | undefined) => {
|
|
63
|
+
highlightedLink.value =
|
|
64
|
+
typeof payload?.value === 'string' ? payload.value : null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const navigateTo = (item: SidebarItem) => {
|
|
68
|
+
router.go(withBase(item.link))
|
|
69
|
+
open.value = false
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Native click on the anchor: let the browser handle modifier-clicks
|
|
73
|
+
// (Cmd/Ctrl/Shift/middle-click) via the `href`; only intercept plain
|
|
74
|
+
// clicks to do SPA navigation. Keyboard Enter on the highlighted item
|
|
75
|
+
// reaches here too — Reka synthesises a `.click()` on the element,
|
|
76
|
+
// which has no modifiers, so it falls through to `navigateTo`.
|
|
77
|
+
const onItemClick = (e: MouseEvent, item: SidebarItem) => {
|
|
78
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) return
|
|
79
|
+
e.preventDefault()
|
|
80
|
+
navigateTo(item)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const onFilterKeydown = (e: KeyboardEvent) => {
|
|
84
|
+
if (e.key !== 'Enter') return
|
|
85
|
+
if (!(e.metaKey || e.ctrlKey)) return
|
|
86
|
+
const link = highlightedLink.value
|
|
87
|
+
if (!link) return
|
|
88
|
+
e.preventDefault()
|
|
89
|
+
e.stopImmediatePropagation()
|
|
90
|
+
window.open(withBase(link), '_blank', 'noopener')
|
|
91
|
+
}
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<template>
|
|
95
|
+
<Dialog v-model:open="open" bare size="xl" position="top" padding-top="10vh">
|
|
96
|
+
<template #default>
|
|
97
|
+
<ListboxRoot
|
|
98
|
+
class="flex flex-col"
|
|
99
|
+
highlight-on-hover
|
|
100
|
+
:model-value="null"
|
|
101
|
+
@highlight="onHighlight"
|
|
102
|
+
>
|
|
103
|
+
<!-- input -->
|
|
104
|
+
<div class="relative">
|
|
105
|
+
<div class="absolute inset-y-0 left-0 flex items-center pl-4.5">
|
|
106
|
+
<span class="lucide-search h-4 w-4 text-ink-gray-6" />
|
|
107
|
+
</div>
|
|
108
|
+
<ListboxFilter
|
|
109
|
+
v-model="filterText"
|
|
110
|
+
auto-focus
|
|
111
|
+
placeholder="Search documentation"
|
|
112
|
+
class="w-full border-none bg-transparent py-3 pl-11.5 pr-4.5 text-base text-ink-gray-7 placeholder-ink-gray-4 focus:ring-0"
|
|
113
|
+
autocomplete="off"
|
|
114
|
+
@keydown="onFilterKeydown"
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<!-- results -->
|
|
119
|
+
<ListboxContent
|
|
120
|
+
class="max-h-96 overflow-auto border-t border-outline-gray-1 dark:border-outline-gray-2"
|
|
121
|
+
>
|
|
122
|
+
<ListboxGroup
|
|
123
|
+
v-for="group in groupedResults"
|
|
124
|
+
:key="group.text"
|
|
125
|
+
class="mb-2 mt-4.5 first:mt-3"
|
|
126
|
+
>
|
|
127
|
+
<ListboxGroupLabel
|
|
128
|
+
class="mb-2.5 block px-4.5 text-base text-ink-gray-5"
|
|
129
|
+
>
|
|
130
|
+
{{ group.text }}
|
|
131
|
+
</ListboxGroupLabel>
|
|
132
|
+
|
|
133
|
+
<div v-for="item in group.items" :key="item.link" class="px-2.5">
|
|
134
|
+
<ListboxItem
|
|
135
|
+
as="a"
|
|
136
|
+
:value="item.link"
|
|
137
|
+
:href="withBase(item.link)"
|
|
138
|
+
class="flex w-full min-w-0 items-center rounded px-2 py-2 text-base font-medium text-ink-gray-7 outline-none data-[highlighted]:bg-surface-gray-3"
|
|
139
|
+
@click="onItemClick($event, item)"
|
|
140
|
+
>
|
|
141
|
+
<span class="overflow-hidden text-ellipsis whitespace-nowrap">
|
|
142
|
+
{{ item.text }}
|
|
143
|
+
</span>
|
|
144
|
+
</ListboxItem>
|
|
145
|
+
</div>
|
|
146
|
+
</ListboxGroup>
|
|
147
|
+
|
|
148
|
+
<div
|
|
149
|
+
v-if="filterText && !hasResults"
|
|
150
|
+
class="my-8 text-center text-base text-ink-gray-6"
|
|
151
|
+
>
|
|
152
|
+
No results for "<b class="text-ink-gray-9">{{ filterText }}</b
|
|
153
|
+
>"
|
|
154
|
+
</div>
|
|
155
|
+
</ListboxContent>
|
|
156
|
+
|
|
157
|
+
<!-- footer -->
|
|
158
|
+
<div
|
|
159
|
+
class="mt-2 flex items-center justify-between border-t border-outline-gray-1 px-2.5 py-2 text-xs text-ink-gray-6 dark:border-outline-gray-2"
|
|
160
|
+
>
|
|
161
|
+
<div class="flex items-center gap-4">
|
|
162
|
+
<div class="flex items-center gap-1">
|
|
163
|
+
<kbd
|
|
164
|
+
class="inline-flex items-center gap-0.5 whitespace-nowrap rounded-sm bg-surface-gray-2 p-0.5 font-[inherit] text-[11px] font-medium leading-normal tracking-[0.02em] text-ink-gray-5"
|
|
165
|
+
>
|
|
166
|
+
<span class="lucide-arrow-down size-4" />
|
|
167
|
+
</kbd>
|
|
168
|
+
<kbd
|
|
169
|
+
class="inline-flex items-center gap-0.5 whitespace-nowrap rounded-sm bg-surface-gray-2 p-0.5 font-[inherit] text-[11px] font-medium leading-normal tracking-[0.02em] text-ink-gray-5"
|
|
170
|
+
>
|
|
171
|
+
<span class="lucide-arrow-up size-4" />
|
|
172
|
+
</kbd>
|
|
173
|
+
<span class="ml-1">to navigate</span>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="flex items-center gap-1">
|
|
176
|
+
<kbd
|
|
177
|
+
class="inline-flex items-center gap-0.5 whitespace-nowrap rounded-sm bg-surface-gray-2 p-0.5 font-[inherit] text-[11px] font-medium leading-normal tracking-[0.02em] text-ink-gray-5"
|
|
178
|
+
>
|
|
179
|
+
<span class="lucide-corner-down-left size-4" />
|
|
180
|
+
</kbd>
|
|
181
|
+
<span class="ml-1">to select</span>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="flex items-center gap-1">
|
|
184
|
+
<kbd
|
|
185
|
+
class="inline-flex items-center gap-0.5 whitespace-nowrap rounded-sm bg-surface-gray-2 p-0.5 font-[inherit] text-[11px] font-medium leading-normal tracking-[0.02em] text-ink-gray-5"
|
|
186
|
+
>
|
|
187
|
+
<span class="lucide-command w-3 h-3" />
|
|
188
|
+
<span class="lucide-corner-down-left size-4" />
|
|
189
|
+
</kbd>
|
|
190
|
+
<span class="ml-1">new tab</span>
|
|
191
|
+
</div>
|
|
192
|
+
<div class="flex items-center gap-1">
|
|
193
|
+
<kbd
|
|
194
|
+
class="inline-flex items-center gap-0.5 whitespace-nowrap rounded-sm bg-surface-gray-2 p-0.5 px-1 font-[inherit] font-medium leading-normal tracking-[0.02em] text-sm text-ink-gray-5"
|
|
195
|
+
>
|
|
196
|
+
esc
|
|
197
|
+
</kbd>
|
|
198
|
+
<span class="ml-1">to close</span>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
<div class="flex items-center gap-1">
|
|
202
|
+
<kbd
|
|
203
|
+
class="inline-flex items-center gap-0.5 whitespace-nowrap rounded-sm bg-surface-gray-2 p-0.5 font-[inherit] text-[11px] font-medium leading-normal tracking-[0.02em] text-ink-gray-5"
|
|
204
|
+
>
|
|
205
|
+
<span class="lucide-command w-3 h-3" />
|
|
206
|
+
<span class="text-sm">K</span>
|
|
207
|
+
</kbd>
|
|
208
|
+
<span class="ml-1">to open</span>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</ListboxRoot>
|
|
212
|
+
</template>
|
|
213
|
+
</Dialog>
|
|
214
|
+
</template>
|