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
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { inject, provide, type ComputedRef, type InjectionKey, type Ref } from 'vue'
|
|
2
|
+
import type { ListDivider } from './types'
|
|
3
|
+
|
|
4
|
+
// Everything a List provides to its descendants. Internal — the public
|
|
5
|
+
// contract is the components' props/models and the CSS hooks
|
|
6
|
+
// (`--list-columns`, `--list-gap`, data-slot/data-state attributes).
|
|
7
|
+
export interface ListContext {
|
|
8
|
+
divider: ComputedRef<ListDivider>
|
|
9
|
+
selectable: ComputedRef<boolean>
|
|
10
|
+
rowHeight: ComputedRef<number | undefined>
|
|
11
|
+
|
|
12
|
+
// Header presence drives ARIA roles: list/listitem without a header,
|
|
13
|
+
// table/row/columnheader/cell with one.
|
|
14
|
+
hasHeader: Ref<boolean>
|
|
15
|
+
|
|
16
|
+
isSelected: (value: string) => boolean
|
|
17
|
+
toggleSelection: (value: string) => void
|
|
18
|
+
|
|
19
|
+
// Header select-all. <ListRows> feeds the full selectable universe via
|
|
20
|
+
// `setAllValues` — it holds the complete `items` array even when the rows are
|
|
21
|
+
// virtualized, so the header checkbox can reflect/toggle "all" without every
|
|
22
|
+
// row being mounted. `selectAllState` drives the header checkbox's
|
|
23
|
+
// checked/indeterminate/empty rendering.
|
|
24
|
+
setAllValues: (values: string[]) => void
|
|
25
|
+
selectAllState: ComputedRef<'none' | 'some' | 'all'>
|
|
26
|
+
toggleSelectAll: () => void
|
|
27
|
+
|
|
28
|
+
// Single "active" row (v-model:active) — the one currently open/highlighted,
|
|
29
|
+
// separate from the checkbox `selection` set. `activatable` is true only when
|
|
30
|
+
// the List actually binds v-model:active, so plain navigation lists opt out.
|
|
31
|
+
activatable: ComputedRef<boolean>
|
|
32
|
+
isActive: (value: string) => boolean
|
|
33
|
+
activate: (value: string) => void
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const listContextKey: InjectionKey<ListContext> = Symbol('frappe-ui:list')
|
|
37
|
+
|
|
38
|
+
export function provideListContext(context: ListContext) {
|
|
39
|
+
provide(listContextKey, context)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function useListContext() {
|
|
43
|
+
return inject(listContextKey, null)
|
|
44
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
<!-- Auto Generated by scripts/propsgen.ts -->
|
|
2
|
+
<script setup>
|
|
3
|
+
import PropsTable from '@/components/Docs/PropsTable.vue'
|
|
4
|
+
import SlotsTable from '@/components/Docs/SlotsTable.vue'
|
|
5
|
+
import EmitsTable from '@/components/Docs/EmitsTable.vue'
|
|
6
|
+
|
|
7
|
+
const listProps = [
|
|
8
|
+
{
|
|
9
|
+
name: 'columns',
|
|
10
|
+
description: 'Grid track sizes, written to the `--list-columns` CSS var shared by the\nheader and every row. Defaults to the feed template\n`[\'auto\', \'minmax(0,1fr)\', \'auto\']` (leading media, content, trailing).\nTable-style lists must pass deterministic track sizes — `auto` tracks\nsize independently per row.',
|
|
11
|
+
required: false,
|
|
12
|
+
type: 'string[]'
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'divider',
|
|
16
|
+
description: 'Divider treatment between rows: `inset` starts at the content column\n(the text edge), `full` spans all columns. Defaults to `inset` with the\ndefault feed template, `full` when `columns` is set.',
|
|
17
|
+
required: false,
|
|
18
|
+
type: 'ListDivider'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'selectable',
|
|
22
|
+
description: 'Reveals the animated checkbox column and switches row click from\nnavigate to toggle. Selected values surface via `v-model:selection`.',
|
|
23
|
+
required: false,
|
|
24
|
+
type: 'boolean'
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'rowHeight',
|
|
28
|
+
description: 'Fixed row height in px (sets `--list-row-height`). Required for\nvirtualization; without it rows size to their content. Responsive\nheights are non-virtual — set them with classes on the rows instead.',
|
|
29
|
+
required: false,
|
|
30
|
+
type: 'number'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'selection',
|
|
34
|
+
description: '',
|
|
35
|
+
required: false,
|
|
36
|
+
type: 'string[]',
|
|
37
|
+
default: '[]'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'active',
|
|
41
|
+
description: '',
|
|
42
|
+
required: false,
|
|
43
|
+
type: 'string'
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
const listSlots = [
|
|
48
|
+
{
|
|
49
|
+
name: 'default',
|
|
50
|
+
description: '',
|
|
51
|
+
type: '{}'
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
const listEmits = [
|
|
56
|
+
{
|
|
57
|
+
name: 'update:selection',
|
|
58
|
+
description: 'Fired when the selection changes.',
|
|
59
|
+
type: '[value: string[]]'
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'update:active',
|
|
63
|
+
description: 'Fired when the active changes.',
|
|
64
|
+
type: '[value: string | undefined]'
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
const listRowProps = [
|
|
69
|
+
{
|
|
70
|
+
name: 'to',
|
|
71
|
+
description: 'Renders the row as a RouterLink. Without `to`, a row with a click\nlistener renders as a button; otherwise a plain div.',
|
|
72
|
+
required: false,
|
|
73
|
+
type: 'string | kt | Tt'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'value',
|
|
77
|
+
description: 'Row key — the `selection` key when `selectable` and the `v-model:active`\nkey. Required whenever the list uses either.',
|
|
78
|
+
required: false,
|
|
79
|
+
type: 'string'
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'onClick',
|
|
83
|
+
description: 'Fired when the row is activated, unless selection mode claims the click.',
|
|
84
|
+
required: false,
|
|
85
|
+
type: '((event: MouseEvent) => void)'
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
const listRowSlots = [
|
|
90
|
+
{
|
|
91
|
+
name: 'default',
|
|
92
|
+
description: '',
|
|
93
|
+
type: '{}'
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
const listCellSlots = [
|
|
98
|
+
{
|
|
99
|
+
name: 'default',
|
|
100
|
+
description: '',
|
|
101
|
+
type: '{}'
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
const listHeaderSlots = [
|
|
106
|
+
{
|
|
107
|
+
name: 'default',
|
|
108
|
+
description: '',
|
|
109
|
+
type: '{}'
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
const listHeaderCellSlots = [
|
|
114
|
+
{
|
|
115
|
+
name: 'default',
|
|
116
|
+
description: 'Column label.',
|
|
117
|
+
type: 'any'
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'prefix',
|
|
121
|
+
description: 'Leading adornment, rendered before the label.',
|
|
122
|
+
type: 'any'
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'suffix',
|
|
126
|
+
description: 'Trailing adornment, rendered after the label.',
|
|
127
|
+
type: 'any'
|
|
128
|
+
}
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
const listHeaderCellSortProps = [
|
|
132
|
+
{
|
|
133
|
+
name: 'direction',
|
|
134
|
+
description: 'Active sort direction for this column, `null`/omitted when inactive.\nThe cell is controlled — sort state and toggle rules are app-owned:\nupdate whatever drives your ordering in the `click` handler.',
|
|
135
|
+
required: false,
|
|
136
|
+
type: 'ListSortDirection | null'
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'align',
|
|
140
|
+
description: 'Horizontal alignment of the header content. `\'end\'` right-aligns the cell\n(for numeric/right-aligned columns) *and* moves the sort glyph to the\nleading side, so the label stays flush with the column\'s right edge and\nlines up with the values below. Defaults to `\'start\'`.',
|
|
141
|
+
required: false,
|
|
142
|
+
type: '"start" | "end"'
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
|
|
146
|
+
const listHeaderCellSortSlots = [
|
|
147
|
+
{
|
|
148
|
+
name: 'default',
|
|
149
|
+
description: 'Column label.',
|
|
150
|
+
type: 'any'
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'prefix',
|
|
154
|
+
description: 'Leading adornment, rendered before the label.',
|
|
155
|
+
type: '{ direction: "desc" | "asc" | null; }'
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'suffix',
|
|
159
|
+
description: 'Sort glyph. Optional — the cell renders a built-in arrow from `direction`\nby default. Provide this to override (e.g. a custom lucide span). The cell\nowns the reveal: an inactive column\'s glyph shows on hover.',
|
|
160
|
+
type: '{ direction: "desc" | "asc" | null; }'
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
const listHeaderCellSortEmits = [
|
|
165
|
+
{
|
|
166
|
+
name: 'click',
|
|
167
|
+
description: '',
|
|
168
|
+
type: '[event: MouseEvent]'
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
const listRowsProps = [
|
|
173
|
+
{
|
|
174
|
+
name: 'items',
|
|
175
|
+
description: 'Items to iterate — one default-slot render per item.',
|
|
176
|
+
required: true,
|
|
177
|
+
type: 'T[]'
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'rowKey',
|
|
181
|
+
description: 'How to derive a row\'s identity. A string reads that property off the item;\na function computes it. Drives the render `:key`, the header select-all\nuniverse, and the scoped `value` slot prop. Defaults to the item\'s `name`,\nthen `id`, then the index.',
|
|
182
|
+
required: false,
|
|
183
|
+
type: 'string | ((item: T, index: number) => PropertyKey)'
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: 'virtual',
|
|
187
|
+
description: 'Window the rows (vueuse useVirtualList) so only rows near the viewport\nmount. `itemHeight` defaults to the List\'s `rowHeight`; the scroll\ncontainer is the nearest scrollable ancestor.',
|
|
188
|
+
required: false,
|
|
189
|
+
type: 'boolean | ListVirtualOptions'
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
const listRowsSlots = [
|
|
194
|
+
{
|
|
195
|
+
name: 'default',
|
|
196
|
+
description: '',
|
|
197
|
+
type: '{ item: T; index: number; value: string; }'
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
const listGroupProps = [
|
|
202
|
+
{
|
|
203
|
+
name: 'label',
|
|
204
|
+
description: 'Section label shown in the group header. Overridden by the #header slot.',
|
|
205
|
+
required: false,
|
|
206
|
+
type: 'string'
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: 'sticky',
|
|
210
|
+
description: 'Pin the group header to the top of the scroll container while its rows\nscroll under it. Off by default.',
|
|
211
|
+
required: false,
|
|
212
|
+
type: 'boolean'
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
const listGroupSlots = [
|
|
217
|
+
{
|
|
218
|
+
name: 'default',
|
|
219
|
+
description: 'The group\'s rows — `<ListRow>` elements.',
|
|
220
|
+
type: 'any'
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: 'header',
|
|
224
|
+
description: 'Replaces the header content (the label).',
|
|
225
|
+
type: 'any'
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
</script>
|
|
229
|
+
|
|
230
|
+
## API Reference
|
|
231
|
+
|
|
232
|
+
### List
|
|
233
|
+
|
|
234
|
+
<PropsTable folder="list" name="List" :data="listProps"/>
|
|
235
|
+
|
|
236
|
+
<SlotsTable :data="listSlots"/>
|
|
237
|
+
|
|
238
|
+
<EmitsTable :data="listEmits"/>
|
|
239
|
+
|
|
240
|
+
### ListRow
|
|
241
|
+
|
|
242
|
+
<PropsTable folder="list" name="ListRow" :data="listRowProps"/>
|
|
243
|
+
|
|
244
|
+
<SlotsTable :data="listRowSlots"/>
|
|
245
|
+
|
|
246
|
+
### ListCell
|
|
247
|
+
|
|
248
|
+
<SlotsTable :data="listCellSlots"/>
|
|
249
|
+
|
|
250
|
+
### ListHeader
|
|
251
|
+
|
|
252
|
+
<SlotsTable :data="listHeaderSlots"/>
|
|
253
|
+
|
|
254
|
+
### ListHeaderCell
|
|
255
|
+
|
|
256
|
+
<SlotsTable :data="listHeaderCellSlots"/>
|
|
257
|
+
|
|
258
|
+
### ListHeaderCellSort
|
|
259
|
+
|
|
260
|
+
<PropsTable folder="list" name="ListHeaderCellSort" :data="listHeaderCellSortProps"/>
|
|
261
|
+
|
|
262
|
+
<SlotsTable :data="listHeaderCellSortSlots"/>
|
|
263
|
+
|
|
264
|
+
<EmitsTable :data="listHeaderCellSortEmits"/>
|
|
265
|
+
|
|
266
|
+
### ListRows
|
|
267
|
+
|
|
268
|
+
<PropsTable folder="list" name="ListRows" :data="listRowsProps"/>
|
|
269
|
+
|
|
270
|
+
<SlotsTable :data="listRowsSlots"/>
|
|
271
|
+
|
|
272
|
+
### ListGroup
|
|
273
|
+
|
|
274
|
+
<PropsTable folder="list" name="ListGroup" :data="listGroupProps"/>
|
|
275
|
+
|
|
276
|
+
<SlotsTable :data="listGroupSlots"/>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# List
|
|
2
|
+
|
|
3
|
+
Composition-based list primitives under the `frappe-ui/list` subpath. Every list
|
|
4
|
+
surface is one column grid: a feed row is just the default column template, a
|
|
5
|
+
table is an explicit one. The family owns geometry — columns, dividers, hover
|
|
6
|
+
surfaces, selection and sort chrome — and nothing readable: cell contents
|
|
7
|
+
(typography, avatars, badges, unread emphasis) are entirely app-authored.
|
|
8
|
+
|
|
9
|
+
Not to be confused with the config-driven `ListView` in the main entry — that
|
|
10
|
+
stays untouched; import from `frappe-ui/list` for this family.
|
|
11
|
+
|
|
12
|
+
## Feed mode
|
|
13
|
+
|
|
14
|
+
The default template (`auto`, `minmax(0,1fr)`, `auto`) fits leading media,
|
|
15
|
+
content, and a right-aligned trailing cell. Rows with `to` render as
|
|
16
|
+
RouterLinks, rows with a click listener as buttons. `selectable` reveals the
|
|
17
|
+
animated checkbox column and switches row click from navigate to toggle;
|
|
18
|
+
selected values surface through `v-model:selection`. When a `ListHeader` is
|
|
19
|
+
present, a select-all checkbox appears in it automatically — checked when every
|
|
20
|
+
row is selected, mixed when only some are, and toggling all rows on or off. It
|
|
21
|
+
reasons over the full `ListRows` items, so it covers virtualized rows too.
|
|
22
|
+
`ListRows` resolves each row's identity once and exposes it as the scoped
|
|
23
|
+
`value` prop. The identity defaults to the item's `name`/`id`; pass `row-key` (a
|
|
24
|
+
field name or `(item, index) => key`) when the row should use a different field.
|
|
25
|
+
|
|
26
|
+
Dividers default to `inset`: they start at the content column (the text edge) by
|
|
27
|
+
construction, never render above the first row, and hide around a hovered row so
|
|
28
|
+
the rounded hover surface floats free.
|
|
29
|
+
|
|
30
|
+
<ComponentPreview name="List-Feed" />
|
|
31
|
+
|
|
32
|
+
## Active row
|
|
33
|
+
|
|
34
|
+
A master–detail list (a mail inbox, a file browser) tracks one open row. Bind
|
|
35
|
+
`v-model:active` to a row `value` and the List owns the rest: it highlights that
|
|
36
|
+
row and hides the dividers hugging it — above and below — so its rounded surface
|
|
37
|
+
floats free, like a hovered row but persistent. Clicking a row sets `active`;
|
|
38
|
+
unlike `selectable`, activation is additive, so the row's own `@click` and `to`
|
|
39
|
+
navigation still run. It's single-select and independent of the multi-select
|
|
40
|
+
checkbox `selection` — and works in feed or column mode.
|
|
41
|
+
|
|
42
|
+
```vue
|
|
43
|
+
<List v-model:active="openId">
|
|
44
|
+
<ListRows :items="threads" v-slot="{ value }">
|
|
45
|
+
<ListRow :value="value">…</ListRow>
|
|
46
|
+
</ListRows>
|
|
47
|
+
</List>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Column mode
|
|
51
|
+
|
|
52
|
+
Pass explicit `columns` (deterministic track sizes — `auto` tracks size
|
|
53
|
+
independently per row) and a `ListHeader`. Header and rows share one
|
|
54
|
+
`--list-columns` template, so they can never drift.
|
|
55
|
+
|
|
56
|
+
`ListHeaderCell` is a plain label with optional `#prefix` / `#suffix`
|
|
57
|
+
adornments. Sortable columns use `ListHeaderCellSort` instead — a controlled
|
|
58
|
+
sort button: you hand it the active `direction` (`asc` / `desc` / `null`) and
|
|
59
|
+
update your own sort state in its `click` handler. Your code owns the state,
|
|
60
|
+
toggle rules, direction glyphs (via the scoped `#suffix="{ direction }"` slot),
|
|
61
|
+
and whether ordering happens client-side or through `useList` orderBy. The cell
|
|
62
|
+
keeps only the behavioral chrome: a real button, `aria-sort`, the tooltip, and
|
|
63
|
+
revealing an inactive column's suffix on hover. Both variants render the same
|
|
64
|
+
`data-slot="list-header-cell"` geometry, so mixing them in one header is
|
|
65
|
+
seamless.
|
|
66
|
+
|
|
67
|
+
<ComponentPreview name="List-Columns" />
|
|
68
|
+
|
|
69
|
+
## Virtual rows
|
|
70
|
+
|
|
71
|
+
`ListRows` iterates items through its scoped slot; with `virtual`, only rows
|
|
72
|
+
near the viewport mount. The scoped slot receives `{ item, index, value }`,
|
|
73
|
+
where `value` is the string row identity used by select-all and active-row
|
|
74
|
+
state. The scroll container is the nearest scrollable ancestor — the list
|
|
75
|
+
windows against an app-owned scroll area (a settings body, the page) and keeps
|
|
76
|
+
its scrollbar. `itemHeight` defaults to the List's `rowHeight`. The underlying
|
|
77
|
+
composable, `useVirtualRows`, is exported for exotic cases.
|
|
78
|
+
|
|
79
|
+
<ComponentPreview name="List-Virtual" csr="true" />
|
|
80
|
+
|
|
81
|
+
## Styling hooks
|
|
82
|
+
|
|
83
|
+
`--list-columns` and `--list-gap` (default `0.5rem`) are public hooks on the
|
|
84
|
+
List — override them with plain classes, responsively if needed. People-style
|
|
85
|
+
lists collapse to a feed on mobile with no dedicated API:
|
|
86
|
+
|
|
87
|
+
```vue
|
|
88
|
+
<List
|
|
89
|
+
:columns="['minmax(8rem,1fr)', '5.5rem', '5.5rem']"
|
|
90
|
+
class="max-sm:[--list-columns:auto_minmax(0,1fr)_auto]"
|
|
91
|
+
>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
with `max-sm:hidden` on the numeric cells and the `ListHeader`.
|
|
95
|
+
|
|
96
|
+
For `--list-gap` and `--list-row-padding-x` (the content inset shared by
|
|
97
|
+
interactive rows — default `0.75rem` — and the column header, so setting it on
|
|
98
|
+
the `List` aligns both), the frappe-ui Tailwind preset ships spacing-scale
|
|
99
|
+
utilities — `list-gap-*` and `list-row-px-*` — so the usual authoring form is
|
|
100
|
+
`max-sm:list-gap-3 sm:list-gap-4` rather than raw `[--list-gap:0.75rem]`
|
|
101
|
+
properties. Both forms hit the same CSS vars.
|
|
102
|
+
|
|
103
|
+
Cells (and plain header cells) are flex containers with `items-center` — align
|
|
104
|
+
content with justify utilities (`class="justify-end"` for numeric columns),
|
|
105
|
+
responsively if needed. For sortable numeric headers, use
|
|
106
|
+
`<ListHeaderCellSort align="end">` so the sort glyph moves to the leading side
|
|
107
|
+
and the label stays flush with the column edge.
|
|
108
|
+
|
|
109
|
+
Slots for CSS targeting:
|
|
110
|
+
`data-slot="list | list-header | list-header-cell | list-row | list-cell | list-row-checkbox | list-divider"`.
|
|
111
|
+
State: `data-state="selected"` (checkbox selection), `data-active` (+
|
|
112
|
+
`aria-current`, the `v-model:active` row) and `data-interactive` on rows,
|
|
113
|
+
`data-sort` on the active header cell.
|
|
114
|
+
|
|
115
|
+
Accessibility follows header presence: `role="list"` / `"listitem"` without a
|
|
116
|
+
`ListHeader`, `table` / `row` / `columnheader` / `cell` (plus `aria-sort`) with
|
|
117
|
+
one.
|
|
118
|
+
|
|
119
|
+
<!-- @include: ./list.api.md -->
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
|
+
import { Avatar, Button } from 'frappe-ui'
|
|
4
|
+
import {
|
|
5
|
+
List,
|
|
6
|
+
ListRow,
|
|
7
|
+
ListCell,
|
|
8
|
+
ListHeader,
|
|
9
|
+
ListHeaderCell,
|
|
10
|
+
ListHeaderCellSort,
|
|
11
|
+
ListRows,
|
|
12
|
+
} from 'frappe-ui/list'
|
|
13
|
+
|
|
14
|
+
const members = [
|
|
15
|
+
{ name: 'Rosa Diaz', email: 'rosa@example.com', role: 'Admin', since: '2021-06' },
|
|
16
|
+
{ name: 'Jake Peralta', email: 'jake@example.com', role: 'Member', since: '2022-01' },
|
|
17
|
+
{ name: 'Amy Santiago', email: 'amy@example.com', role: 'Admin', since: '2020-11' },
|
|
18
|
+
{ name: 'Terry Jeffords', email: 'terry@example.com', role: 'Member', since: '2023-03' },
|
|
19
|
+
{ name: 'Raymond Holt', email: 'holt@example.com', role: 'Guest', since: '2024-08' },
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
// Sort state, toggle rules, comparator, and direction icons are all app
|
|
23
|
+
// code — the header cells only render the chrome for whatever `direction`
|
|
24
|
+
// you hand them.
|
|
25
|
+
type Field = 'name' | 'role' | 'since'
|
|
26
|
+
|
|
27
|
+
function sortIcon(direction: 'asc' | 'desc' | null) {
|
|
28
|
+
if (!direction) return 'lucide-arrow-up-down'
|
|
29
|
+
return direction === 'asc' ? 'lucide-arrow-up' : 'lucide-arrow-down'
|
|
30
|
+
}
|
|
31
|
+
const sortField = ref<Field>('name')
|
|
32
|
+
const sortDirection = ref<'asc' | 'desc'>('asc')
|
|
33
|
+
|
|
34
|
+
function toggleSort(field: Field, firstDirection: 'asc' | 'desc' = 'asc') {
|
|
35
|
+
if (sortField.value === field) {
|
|
36
|
+
sortDirection.value = sortDirection.value === 'asc' ? 'desc' : 'asc'
|
|
37
|
+
} else {
|
|
38
|
+
sortField.value = field
|
|
39
|
+
sortDirection.value = firstDirection
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function directionFor(field: Field) {
|
|
44
|
+
return sortField.value === field ? sortDirection.value : null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const sortedMembers = computed(() => {
|
|
48
|
+
const factor = sortDirection.value === 'desc' ? -1 : 1
|
|
49
|
+
return [...members].sort(
|
|
50
|
+
(a, b) => factor * a[sortField.value].localeCompare(b[sortField.value]),
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<List class="w-full" :columns="['minmax(0,1fr)', '7rem', '8rem', '3rem']" :row-height="56">
|
|
57
|
+
<ListHeader>
|
|
58
|
+
<ListHeaderCellSort :direction="directionFor('name')" @click="toggleSort('name')">
|
|
59
|
+
Member
|
|
60
|
+
<template #suffix="{ direction }">
|
|
61
|
+
<span class="block size-3.5" :class="sortIcon(direction)" />
|
|
62
|
+
</template>
|
|
63
|
+
</ListHeaderCellSort>
|
|
64
|
+
<ListHeaderCellSort :direction="directionFor('role')" @click="toggleSort('role')">
|
|
65
|
+
Role
|
|
66
|
+
<template #suffix="{ direction }">
|
|
67
|
+
<span class="block size-3.5" :class="sortIcon(direction)" />
|
|
68
|
+
</template>
|
|
69
|
+
</ListHeaderCellSort>
|
|
70
|
+
<ListHeaderCellSort
|
|
71
|
+
:direction="directionFor('since')"
|
|
72
|
+
class="justify-end"
|
|
73
|
+
@click="toggleSort('since', 'desc')"
|
|
74
|
+
>
|
|
75
|
+
Member since
|
|
76
|
+
<template #suffix="{ direction }">
|
|
77
|
+
<span class="block size-3.5" :class="sortIcon(direction)" />
|
|
78
|
+
</template>
|
|
79
|
+
</ListHeaderCellSort>
|
|
80
|
+
<ListHeaderCell />
|
|
81
|
+
</ListHeader>
|
|
82
|
+
<ListRows :items="sortedMembers" v-slot="{ item: member }">
|
|
83
|
+
<ListRow>
|
|
84
|
+
<ListCell>
|
|
85
|
+
<Avatar :label="member.name" size="xl" />
|
|
86
|
+
<div class="ml-3 min-w-0">
|
|
87
|
+
<div class="truncate text-base text-ink-gray-8">{{ member.name }}</div>
|
|
88
|
+
<div class="mt-0.5 truncate text-sm text-ink-gray-5">{{ member.email }}</div>
|
|
89
|
+
</div>
|
|
90
|
+
</ListCell>
|
|
91
|
+
<ListCell>
|
|
92
|
+
<span class="text-base text-ink-gray-7">{{ member.role }}</span>
|
|
93
|
+
</ListCell>
|
|
94
|
+
<ListCell class="justify-end">
|
|
95
|
+
<span class="text-base text-ink-gray-6">{{ member.since }}</span>
|
|
96
|
+
</ListCell>
|
|
97
|
+
<ListCell class="justify-end">
|
|
98
|
+
<Button variant="ghost" icon="lucide-trash-2" label="Remove member" />
|
|
99
|
+
</ListCell>
|
|
100
|
+
</ListRow>
|
|
101
|
+
</ListRows>
|
|
102
|
+
</List>
|
|
103
|
+
</template>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import { Avatar, Badge, Button } from 'frappe-ui'
|
|
4
|
+
import { List, ListRow, ListCell } from 'frappe-ui/list'
|
|
5
|
+
|
|
6
|
+
const discussions = [
|
|
7
|
+
{
|
|
8
|
+
name: '1',
|
|
9
|
+
title: 'Weekly sync notes',
|
|
10
|
+
author: 'Rosa Diaz',
|
|
11
|
+
comment: 'Sounds good, let us ship it on Monday',
|
|
12
|
+
time: '2 h',
|
|
13
|
+
comments: 4,
|
|
14
|
+
unread: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: '2',
|
|
18
|
+
title: 'Redesigning the onboarding flow',
|
|
19
|
+
author: 'Jake Peralta',
|
|
20
|
+
comment: 'I added the new mockups to the page',
|
|
21
|
+
time: '5 h',
|
|
22
|
+
comments: 12,
|
|
23
|
+
unread: false,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: '3',
|
|
27
|
+
title: 'Q3 hiring plan',
|
|
28
|
+
author: 'Amy Santiago',
|
|
29
|
+
comment: 'Two backend roles and one designer',
|
|
30
|
+
time: '1 d',
|
|
31
|
+
comments: 7,
|
|
32
|
+
unread: true,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: '4',
|
|
36
|
+
title: 'Incident review: search downtime',
|
|
37
|
+
author: 'Terry Jeffords',
|
|
38
|
+
comment: 'Root cause was the index rebuild',
|
|
39
|
+
time: '2 d',
|
|
40
|
+
comments: 9,
|
|
41
|
+
unread: false,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: '5',
|
|
45
|
+
title: 'Docs sprint retrospective',
|
|
46
|
+
author: 'Raymond Holt',
|
|
47
|
+
comment: 'Velocity was acceptable.',
|
|
48
|
+
time: '4 d',
|
|
49
|
+
comments: 3,
|
|
50
|
+
unread: false,
|
|
51
|
+
},
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
const selectable = ref(false)
|
|
55
|
+
const selection = ref<string[]>([])
|
|
56
|
+
|
|
57
|
+
function toggleSelectMode() {
|
|
58
|
+
selectable.value = !selectable.value
|
|
59
|
+
selection.value = []
|
|
60
|
+
}
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<template>
|
|
64
|
+
<div class="w-full">
|
|
65
|
+
<div class="mb-2 flex h-7 items-center justify-end gap-3">
|
|
66
|
+
<span v-if="selection.length" class="text-sm text-ink-gray-5">
|
|
67
|
+
{{ selection.length }} selected
|
|
68
|
+
</span>
|
|
69
|
+
<Button @click="toggleSelectMode">
|
|
70
|
+
{{ selectable ? 'Done' : 'Select' }}
|
|
71
|
+
</Button>
|
|
72
|
+
</div>
|
|
73
|
+
<List :selectable="selectable" v-model:selection="selection" :row-height="60">
|
|
74
|
+
<ListRow
|
|
75
|
+
v-for="discussion in discussions"
|
|
76
|
+
:key="discussion.name"
|
|
77
|
+
:value="discussion.name"
|
|
78
|
+
@click="() => {}"
|
|
79
|
+
>
|
|
80
|
+
<ListCell>
|
|
81
|
+
<Avatar :label="discussion.author" size="2xl" />
|
|
82
|
+
</ListCell>
|
|
83
|
+
<ListCell>
|
|
84
|
+
<div class="min-w-0">
|
|
85
|
+
<div
|
|
86
|
+
class="truncate text-base text-ink-gray-8"
|
|
87
|
+
:class="discussion.unread && 'font-semibold'"
|
|
88
|
+
>
|
|
89
|
+
{{ discussion.title }}
|
|
90
|
+
</div>
|
|
91
|
+
<div class="mt-1 truncate text-base text-ink-gray-5">
|
|
92
|
+
{{ discussion.author }}: {{ discussion.comment }}
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</ListCell>
|
|
96
|
+
<ListCell class="justify-end">
|
|
97
|
+
<div class="flex flex-col items-end gap-1">
|
|
98
|
+
<span class="text-sm text-ink-gray-5">{{ discussion.time }}</span>
|
|
99
|
+
<Badge>{{ discussion.comments }}</Badge>
|
|
100
|
+
</div>
|
|
101
|
+
</ListCell>
|
|
102
|
+
</ListRow>
|
|
103
|
+
</List>
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { List, ListRow, ListCell, ListRows } from 'frappe-ui/list'
|
|
3
|
+
|
|
4
|
+
const items = Array.from({ length: 1000 }, (_, i) => ({
|
|
5
|
+
id: String(i + 1),
|
|
6
|
+
title: `Task ${i + 1}`,
|
|
7
|
+
status: i % 3 === 0 ? 'Done' : i % 3 === 1 ? 'In progress' : 'Backlog',
|
|
8
|
+
}))
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<!-- The scroll container is app-owned: ListRows finds the nearest
|
|
13
|
+
scrollable ancestor and windows against it. -->
|
|
14
|
+
<div class="h-72 w-full overflow-y-auto rounded border">
|
|
15
|
+
<List :columns="['3rem', 'minmax(0,1fr)', '6rem']" :row-height="44" class="px-2">
|
|
16
|
+
<ListRows :items="items" virtual v-slot="{ item }">
|
|
17
|
+
<ListRow>
|
|
18
|
+
<ListCell>
|
|
19
|
+
<span class="text-sm text-ink-gray-4">#{{ item.id }}</span>
|
|
20
|
+
</ListCell>
|
|
21
|
+
<ListCell>
|
|
22
|
+
<span class="truncate text-base text-ink-gray-8">{{ item.title }}</span>
|
|
23
|
+
</ListCell>
|
|
24
|
+
<ListCell class="justify-end">
|
|
25
|
+
<span class="text-sm text-ink-gray-5">{{ item.status }}</span>
|
|
26
|
+
</ListCell>
|
|
27
|
+
</ListRow>
|
|
28
|
+
</ListRows>
|
|
29
|
+
</List>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|