| // Copyright (C) 2025 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| import m from 'mithril'; |
| import {classNames} from '../../base/classnames'; |
| import type {App} from '../../public/app'; |
| import {renderAccordion} from './demos/accordion_demo'; |
| import {anchor} from './demos/anchor_demo'; |
| import {renderButtonDemo} from './demos/button_demo'; |
| import {renderButtonGroupDemo} from './demos/button_group_demo'; |
| import {renderCallout} from './demos/callout_demo'; |
| import {renderCard} from './demos/card_demo'; |
| import {cardStack} from './demos/cardstack_demo'; |
| import {renderCheckbox} from './demos/checkbox_demo'; |
| import {renderChip} from './demos/chip_demo'; |
| import {renderCodeSnippet} from './demos/code_snippet_demo'; |
| import {renderCopyableLink} from './demos/copyable_link_demo'; |
| import {cursorTooltip} from './demos/cursor_tooltip_demo'; |
| import {renderDataGrid} from './demos/datagrid_demo'; |
| import {renderDrawerPanel} from './demos/drawer_panel_demo'; |
| import {renderEditor} from './demos/editor_demo'; |
| import {renderEmptyState} from './demos/empty_state_demo'; |
| import {renderForm} from './demos/form_demo'; |
| import {renderGrid} from './demos/grid_demo'; |
| import {renderCharts} from './demos/charts_demo'; |
| import {renderHotkey} from './demos/hotkey_demo'; |
| import {renderIcon} from './demos/icon_demo'; |
| import {renderMenu} from './demos/menu_demo'; |
| import {renderMiddleEllipsis} from './demos/middle_ellipsis_demo'; |
| import {renderModal} from './demos/modal_demo'; |
| import {renderMultiselect} from './demos/multiselect_demo'; |
| import {renderNodeGraph} from './demos/nodegraph_demo'; |
| import {renderPopup} from './demos/popup_demo'; |
| import {popupMenuDemo} from './demos/popup_menu_demo'; |
| import {renderPortal} from './demos/portal_demo'; |
| import {renderResizeHandle} from './demos/resize_handle_demo'; |
| import {radioGroup} from './demos/radio_group_demo'; |
| import {renderSelect} from './demos/select_demo'; |
| import {renderSpinner} from './demos/spinner_demo'; |
| import {renderSplitPanel} from './demos/split_panel_demo'; |
| import {renderCombobox} from './demos/combobox_demo'; |
| import {renderSwitch} from './demos/switch_demo'; |
| import {renderTabs} from './demos/tabs_demo'; |
| import {renderTabStrip} from './demos/tabstrip_demo'; |
| import {renderTagInput} from './demos/tag_input_demo'; |
| import {renderTextInput} from './demos/text_input_demo'; |
| import {renderTextParagraph} from './demos/text_paragraph_demo'; |
| import {renderTooltip} from './demos/tooltip_demo'; |
| import {renderTrackShell} from './demos/track_shell_demo'; |
| import {renderTree} from './demos/tree_demo'; |
| import {renderTreeTable} from './demos/treetable_demo'; |
| import {renderVirtualCanvas} from './demos/virtual_canvas_demo'; |
| |
| interface WidgetSection { |
| readonly id: string; |
| readonly label: string; |
| readonly view: (app: App) => m.Children; |
| } |
| |
| const WIDGET_SECTIONS: WidgetSection[] = [ |
| {id: 'accordion', label: 'Accordion', view: renderAccordion}, |
| {id: 'anchor', label: 'Anchor', view: anchor}, |
| {id: 'button', label: 'Button', view: renderButtonDemo}, |
| {id: 'button-group', label: 'ButtonGroup', view: renderButtonGroupDemo}, |
| {id: 'callout', label: 'Callout', view: renderCallout}, |
| {id: 'card-stack', label: 'CardStack', view: cardStack}, |
| {id: 'card', label: 'Card', view: renderCard}, |
| {id: 'charts', label: 'Charts', view: renderCharts}, |
| {id: 'checkbox', label: 'Checkbox', view: renderCheckbox}, |
| {id: 'chip', label: 'Chip', view: renderChip}, |
| {id: 'codesnippet', label: 'CodeSnippet', view: renderCodeSnippet}, |
| {id: 'combobox', label: 'Combobox', view: renderCombobox}, |
| {id: 'copyablelink', label: 'CopyableLink', view: renderCopyableLink}, |
| {id: 'cursor-tooltip', label: 'CursorTooltip', view: cursorTooltip}, |
| {id: 'datagrid', label: 'DataGrid', view: renderDataGrid}, |
| {id: 'drawer-panel', label: 'DrawerPanel', view: renderDrawerPanel}, |
| {id: 'editor', label: 'Editor', view: renderEditor}, |
| {id: 'emptystate', label: 'EmptyState', view: renderEmptyState}, |
| {id: 'form', label: 'Form', view: renderForm}, |
| {id: 'grid', label: 'Grid', view: renderGrid}, |
| {id: 'hotkey', label: 'Hotkey', view: renderHotkey}, |
| {id: 'icon', label: 'Icon', view: renderIcon}, |
| {id: 'menu', label: 'Menu', view: renderMenu}, |
| {id: 'middleellipsis', label: 'MiddleEllipsis', view: renderMiddleEllipsis}, |
| {id: 'modal', label: 'Modal', view: renderModal}, |
| {id: 'multiselect', label: 'Multiselect', view: renderMultiselect}, |
| {id: 'nodegraph', label: 'NodeGraph', view: renderNodeGraph}, |
| {id: 'popup', label: 'Popup', view: renderPopup}, |
| {id: 'popup-menu', label: 'PopupMenu', view: popupMenuDemo}, |
| {id: 'portal', label: 'Portal', view: renderPortal}, |
| {id: 'resize-handle', label: 'ResizeHandle', view: renderResizeHandle}, |
| {id: 'radio-group', label: 'RadioGroup', view: radioGroup}, |
| {id: 'select', label: 'Select', view: renderSelect}, |
| {id: 'spinner', label: 'Spinner', view: renderSpinner}, |
| {id: 'split-panel', label: 'SplitPanel', view: renderSplitPanel}, |
| {id: 'switch', label: 'Switch', view: renderSwitch}, |
| {id: 'tabs', label: 'Tabs', view: renderTabs}, |
| {id: 'tabstrip', label: 'TabStrip', view: renderTabStrip}, |
| {id: 'taginput', label: 'TagInput', view: renderTagInput}, |
| {id: 'textinput', label: 'TextInput', view: renderTextInput}, |
| {id: 'textparagraph', label: 'TextParagraph', view: renderTextParagraph}, |
| {id: 'tooltip', label: 'Tooltip', view: renderTooltip}, |
| {id: 'trackshell', label: 'TrackShell', view: renderTrackShell}, |
| {id: 'tree', label: 'Tree', view: renderTree}, |
| {id: 'treetable', label: 'TreeTable', view: renderTreeTable}, |
| {id: 'virtualcanvas', label: 'VirtualCanvas', view: renderVirtualCanvas}, |
| ]; |
| |
| export interface WidgetsPageAttrs { |
| readonly app: App; |
| readonly subpage?: string; |
| } |
| |
| export class WidgetsPage implements m.ClassComponent<WidgetsPageAttrs> { |
| view({attrs}: m.Vnode<WidgetsPageAttrs>) { |
| const currentSection = WIDGET_SECTIONS.find( |
| (s) => `/${s.id}` === attrs.subpage, |
| ); |
| |
| return m( |
| '.pf-widgets-page', |
| // Left sidebar menu |
| m( |
| '.pf-widgets-page__menu', |
| {key: 'widgets-menu'}, |
| m( |
| 'nav', |
| WIDGET_SECTIONS.map((sec) => |
| m( |
| '.pf-widgets-page__menu-item', |
| { |
| className: classNames(sec === currentSection && 'pf-active'), |
| onclick: () => { |
| window.location.hash = `#!/widgets/${sec.id}`; |
| }, |
| }, |
| sec.label, |
| ), |
| ), |
| ), |
| ), |
| // Main content area |
| m( |
| '.pf-widgets-page__content-container', |
| {key: currentSection ? currentSection.id : 'no-section'}, |
| m( |
| '.pf-widgets-page__content', |
| currentSection |
| ? currentSection.view(attrs.app) |
| : m( |
| '.pf-widget-intro', |
| m('h1', 'Widgets Showcase'), |
| m('p', [ |
| 'This showcase demonstrates the reusable UI components available in the Perfetto UI framework.', |
| ]), |
| m('p', [ |
| 'Click on a widget name in the menu on the left to view interactive demos and examples.', |
| ]), |
| ), |
| ), |
| ), |
| ); |
| } |
| } |