├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── DESCRIPTION ├── LICENSE ├── MANIFEST.in ├── NAMESPACE ├── Project.toml ├── README-en_US.md ├── README.md ├── bug_fix.py ├── fac-logo.svg ├── feffery_antd_components ├── AntdAccordion.py ├── AntdAffix.py ├── AntdAlert.py ├── AntdAnchor.py ├── AntdAvatar.py ├── AntdAvatarGroup.py ├── AntdBackTop.py ├── AntdBadge.py ├── AntdBreadcrumb.py ├── AntdButton.py ├── AntdCalendar.py ├── AntdCard.py ├── AntdCardGrid.py ├── AntdCardMeta.py ├── AntdCarousel.py ├── AntdCascader.py ├── AntdCenter.py ├── AntdCheckCard.py ├── AntdCheckCardGroup.py ├── AntdCheckableTag.py ├── AntdCheckbox.py ├── AntdCheckboxGroup.py ├── AntdCol.py ├── AntdCollapse.py ├── AntdColorPicker.py ├── AntdComment.py ├── AntdCompact.py ├── AntdConfigProvider.py ├── AntdContent.py ├── AntdCopyText.py ├── AntdCountdown.py ├── AntdCountup.py ├── AntdCustomSkeleton.py ├── AntdDatePicker.py ├── AntdDateRangePicker.py ├── AntdDescriptionItem.py ├── AntdDescriptions.py ├── AntdDivider.py ├── AntdDraggerUpload.py ├── AntdDrawer.py ├── AntdDropdown.py ├── AntdEmpty.py ├── AntdFlex.py ├── AntdFloatButton.py ├── AntdFloatButtonGroup.py ├── AntdFooter.py ├── AntdForm.py ├── AntdFormItem.py ├── AntdFormRender.py ├── AntdHeader.py ├── AntdIcon.py ├── AntdImage.py ├── AntdImageGroup.py ├── AntdInput.py ├── AntdInputNumber.py ├── AntdLayout.py ├── AntdMentions.py ├── AntdMenu.py ├── AntdMessage.py ├── AntdModal.py ├── AntdNotification.py ├── AntdOTP.py ├── AntdPageHeader.py ├── AntdPagination.py ├── AntdParagraph.py ├── AntdPictureUpload.py ├── AntdPopconfirm.py ├── AntdPopover.py ├── AntdPopupCard.py ├── AntdProgress.py ├── AntdQRCode.py ├── AntdRadioGroup.py ├── AntdRate.py ├── AntdResult.py ├── AntdRibbon.py ├── AntdRow.py ├── AntdSegmented.py ├── AntdSegmentedColoring.py ├── AntdSelect.py ├── AntdSider.py ├── AntdSkeleton.py ├── AntdSkeletonAvatar.py ├── AntdSkeletonButton.py ├── AntdSkeletonImage.py ├── AntdSkeletonInput.py ├── AntdSlider.py ├── AntdSpace.py ├── AntdSpin.py ├── AntdSplitter.py ├── AntdSpoiler.py ├── AntdStatistic.py ├── AntdSteps.py ├── AntdSwitch.py ├── AntdTable.py ├── AntdTabs.py ├── AntdTag.py ├── AntdText.py ├── AntdTimePicker.py ├── AntdTimeRangePicker.py ├── AntdTimeline.py ├── AntdTitle.py ├── AntdTooltip.py ├── AntdTour.py ├── AntdTransfer.py ├── AntdTree.py ├── AntdTreeSelect.py ├── AntdUpload.py ├── AntdWatermark.py ├── Fragment.py ├── __init__.py ├── _icons.py ├── _imports_.py ├── alias.py └── utils.py ├── images ├── 公众号.png ├── 国际化示例_de-de.png ├── 国际化示例_en-us.png └── 知识星球.jpg ├── npm-debug.log ├── package.json ├── pytest.ini ├── release-to-test-pypi.sh ├── requirements.txt ├── review_checklist.md ├── ruff.toml ├── setup.py ├── src └── lib │ ├── components │ ├── dataDisplay │ │ ├── AntdAccordion.react.js │ │ ├── AntdAvatar.react.js │ │ ├── AntdAvatarGroup.react.js │ │ ├── AntdBadge.react.js │ │ ├── AntdCarousel.react.js │ │ ├── AntdCheckableTag.react.js │ │ ├── AntdCollapse.react.js │ │ ├── AntdComment.react.js │ │ ├── AntdCountdown.react.js │ │ ├── AntdCountup.react.js │ │ ├── AntdEmpty.react.js │ │ ├── AntdImage.react.js │ │ ├── AntdImageGroup.react.js │ │ ├── AntdPopover.react.js │ │ ├── AntdQRCode.react.js │ │ ├── AntdRibbon.react.js │ │ ├── AntdSegmented.react.js │ │ ├── AntdSpoiler.react.js │ │ ├── AntdStatistic.react.js │ │ ├── AntdTable.react.js │ │ ├── AntdTabs.react.js │ │ ├── AntdTag.react.js │ │ ├── AntdTimeline.react.js │ │ ├── AntdTooltip.react.js │ │ ├── AntdTree.react.js │ │ ├── card │ │ │ ├── AntdCard.react.js │ │ │ ├── AntdCardGrid.react.js │ │ │ └── AntdCardMeta.react.js │ │ └── descriptions │ │ │ ├── AntdDescriptionItem.react.js │ │ │ └── AntdDescriptions.react.js │ ├── dataEntry │ │ ├── AntdCalendar.react.js │ │ ├── AntdCascader.react.js │ │ ├── AntdCheckbox.react.js │ │ ├── AntdCheckboxGroup.react.js │ │ ├── AntdColorPicker.react.js │ │ ├── AntdDatePicker.react.js │ │ ├── AntdDateRangePicker.react.js │ │ ├── AntdInput.react.js │ │ ├── AntdInputNumber.react.js │ │ ├── AntdMentions.react.js │ │ ├── AntdOTP.react.js │ │ ├── AntdRadioGroup.react.js │ │ ├── AntdRate.react.js │ │ ├── AntdSegmentedColoring.react.js │ │ ├── AntdSelect.react.js │ │ ├── AntdSlider.react.js │ │ ├── AntdSwitch.react.js │ │ ├── AntdTimePicker.react.js │ │ ├── AntdTimeRangePicker.react.js │ │ ├── AntdTransfer.react.js │ │ ├── AntdTreeSelect.react.js │ │ ├── check-card │ │ │ ├── AntdCheckCard.react.js │ │ │ └── AntdCheckCardGroup.react.js │ │ ├── form │ │ │ ├── AntdForm.react.js │ │ │ └── AntdFormItem.react.js │ │ └── upload │ │ │ ├── AntdDraggerUpload.react.js │ │ │ ├── AntdPictureUpload.react.js │ │ │ └── AntdUpload.react.js │ ├── feedback │ │ ├── AntdAlert.react.js │ │ ├── AntdDrawer.react.js │ │ ├── AntdMessage.react.js │ │ ├── AntdModal.react.js │ │ ├── AntdNotification.react.js │ │ ├── AntdPopconfirm.react.js │ │ ├── AntdPopupCard.react.js │ │ ├── AntdProgress.react.js │ │ ├── AntdResult.react.js │ │ ├── AntdSpin.react.js │ │ └── skeleton │ │ │ ├── AntdCustomSkeleton.react.js │ │ │ ├── AntdSkeleton.react.js │ │ │ ├── AntdSkeletonAvatar.react.js │ │ │ ├── AntdSkeletonButton.react.js │ │ │ ├── AntdSkeletonImage.react.js │ │ │ └── AntdSkeletonInput.react.js │ ├── formRender │ │ └── AntdFormRender.react.js │ ├── general │ │ ├── AntdButton.react.js │ │ ├── AntdFloatButton.react.js │ │ ├── AntdFloatButtonGroup.react.js │ │ ├── AntdIcon.react.js │ │ └── typography │ │ │ ├── AntdParagraph.react.js │ │ │ ├── AntdText.react.js │ │ │ └── AntdTitle.react.js │ ├── icons.react.js │ ├── layout │ │ ├── AntdCenter.react.js │ │ ├── AntdCompact.react.js │ │ ├── AntdContent.react.js │ │ ├── AntdDivider.react.js │ │ ├── AntdFlex.react.js │ │ ├── AntdFooter.react.js │ │ ├── AntdHeader.react.js │ │ ├── AntdLayout.react.js │ │ ├── AntdSider.react.js │ │ ├── AntdSpace.react.js │ │ ├── AntdSplitter.react.js │ │ └── grid │ │ │ ├── AntdCol.react.js │ │ │ └── AntdRow.react.js │ ├── locales.react.js │ ├── navigation │ │ ├── AntdAnchor.react.js │ │ ├── AntdBreadcrumb.react.js │ │ ├── AntdDropdown.react.js │ │ ├── AntdMenu.react.js │ │ ├── AntdPageHeader.react.js │ │ ├── AntdPagination.react.js │ │ └── AntdSteps.react.js │ ├── other │ │ ├── AntdAffix.react.js │ │ ├── AntdBackTop.react.js │ │ ├── AntdConfigProvider.react.js │ │ ├── AntdCopyText.react.js │ │ ├── AntdTour.react.js │ │ ├── AntdWatermark.react.js │ │ └── Fragment.react.js │ ├── styles.css │ └── utils.js │ ├── contexts │ ├── FormContext.js │ ├── FormItemContext.js │ └── PropsContext.js │ ├── fragments │ ├── AntdTable.react.js │ ├── dataDisplay │ │ ├── AntdAccordion.react.js │ │ ├── AntdAvatar.react.js │ │ ├── AntdAvatarGroup.react.js │ │ ├── AntdBadge.react.js │ │ ├── AntdCarousel.react.js │ │ ├── AntdCheckableTag.react.js │ │ ├── AntdComment.react.js │ │ ├── AntdCountdown.react.js │ │ ├── AntdCountup.react.js │ │ ├── AntdEmpty.react.js │ │ ├── AntdImage.react.js │ │ ├── AntdImageGroup.react.js │ │ ├── AntdPopover.react.js │ │ ├── AntdQRCode.react.js │ │ ├── AntdRibbon.react.js │ │ ├── AntdSegmented.react.js │ │ ├── AntdSpoiler.react.js │ │ ├── AntdTabs.react.js │ │ ├── AntdTag.react.js │ │ ├── AntdTimeline.react.js │ │ ├── AntdTooltip.react.js │ │ ├── AntdTree.react.js │ │ ├── card │ │ │ ├── AntdCard.react.js │ │ │ ├── AntdCardGrid.react.js │ │ │ └── AntdCardMeta.react.js │ │ └── descriptions │ │ │ ├── AntdDescriptionItem.react.js │ │ │ └── AntdDescriptions.react.js │ ├── dataEntry │ │ ├── AntdCalendar.react.js │ │ ├── AntdCascader.react.js │ │ ├── AntdCheckbox.react.js │ │ ├── AntdCheckboxGroup.react.js │ │ ├── AntdColorPicker.react.js │ │ ├── AntdDatePicker.react.js │ │ ├── AntdDateRangePicker.react.js │ │ ├── AntdInput.react.js │ │ ├── AntdInputNumber.react.js │ │ ├── AntdMentions.react.js │ │ ├── AntdOTP.react.js │ │ ├── AntdRadioGroup.react.js │ │ ├── AntdRate.react.js │ │ ├── AntdSegmentedColoring.react.js │ │ ├── AntdSelect.react.js │ │ ├── AntdSlider.react.js │ │ ├── AntdSwitch.react.js │ │ ├── AntdTimePicker.react.js │ │ ├── AntdTimeRangePicker.react.js │ │ ├── AntdTransfer.react.js │ │ ├── AntdTreeSelect.react.js │ │ ├── check-card │ │ │ ├── AntdCheckCard.react.js │ │ │ └── AntdCheckCardGroup.react.js │ │ └── form │ │ │ ├── AntdForm.react.js │ │ │ └── AntdFormItem.react.js │ ├── formRender │ │ └── AntdFormRender.react.js │ └── upload │ │ ├── AntdDraggerUpload.react.js │ │ ├── AntdPictureUpload.react.js │ │ └── AntdUpload.react.js │ ├── hooks │ └── useCss.js │ ├── index.js │ └── store │ └── formStore.js ├── tests ├── dash3.0tests │ ├── AntdQRCode组件loading状态重构 │ │ └── test.py │ ├── AntdTable函数式改造 │ │ └── test.py │ ├── _dashprivate_layout改动测试 │ │ └── test.py │ ├── loading_state改动测试 │ │ └── test.py │ ├── 函数式组件默认值重构 │ │ └── test.py │ ├── 加载动画类组件重构测试 │ │ └── test.py │ └── 组件属性基础持久化重构测试 │ │ └── test.py ├── dataDisplay │ ├── AntdAccordion │ │ ├── feat_size.py │ │ └── feat_styles.py │ ├── AntdCard │ │ └── refactor_delete_props.py │ ├── AntdCarousel │ │ └── feat_auto_play_dot_duration.py │ ├── AntdCollapse │ │ ├── feat_size.py │ │ └── feat_styles.py │ ├── AntdCountdown │ │ ├── feat_finish_event.py │ │ └── refactor_to_timer.py │ ├── AntdCountup │ │ └── refactor_to_timer.py │ ├── AntdDescriptions │ │ └── feat_span_filled.py │ ├── AntdImage │ │ └── debug_preview_toolbar.py │ ├── AntdSegmented │ │ ├── feat_shape.py │ │ ├── feat_simple_options.py │ │ └── feat_vertical.py │ ├── AntdTable │ │ ├── feat_columns_fixed_bool.py │ │ ├── feat_columns_min_width.py │ │ ├── feat_editable_disabled_keys.py │ │ ├── feat_header_align.py │ │ ├── feat_loading.py │ │ ├── feat_mini_chart_color.py │ │ ├── feat_row_class_name.py │ │ ├── feat_row_class_name_func.py │ │ ├── feat_table_scroll.py │ │ ├── fix_context_locale.py │ │ ├── fix_field_bool.py │ │ ├── fix_nested_editable.py │ │ ├── fix_server_side_mode_filter_search.py │ │ ├── fix_summary.py │ │ └── fix_summary_multi_level_header.py │ ├── AntdTabs │ │ ├── feat_item_icon.py │ │ ├── feat_placeholder.py │ │ └── feat_tab_bar_style.py │ ├── AntdTree │ │ └── feat_async_data_load.py │ └── descriptions │ │ └── AntdDescriptions │ │ └── feat_extra.py ├── dataEntry │ ├── AntdCalendar │ │ └── feat_custom_cells.py │ ├── AntdCascader │ │ ├── feat_prefix.py │ │ ├── feat_suffix_icon.py │ │ └── fix_read_only.py │ ├── AntdDatePicker │ │ ├── feat_custom_cells.py │ │ ├── feat_picker_value.py │ │ ├── feat_prefix.py │ │ └── feat_suffix_icon.py │ ├── AntdDateRangePicker │ │ ├── feat_custom_cells.py │ │ ├── feat_picker_value.py │ │ ├── feat_prefix.py │ │ └── feat_suffix_icon.py │ ├── AntdForm │ │ ├── feat_optional_batch_control.py │ │ └── fix_checkbox.py │ ├── AntdRadioGroup │ │ └── feat_block.py │ ├── AntdSelect │ │ ├── feat_locale_ru.py │ │ ├── feat_max_count.py │ │ ├── feat_prefix.py │ │ ├── feat_suffix_icon.py │ │ └── fix_read_only.py │ ├── AntdTimePicker │ │ ├── feat_prefix.py │ │ └── feat_suffix_icon.py │ ├── AntdTimeRangePicker │ │ ├── feat_prefix.py │ │ └── feat_suffix_icon.py │ ├── AntdTreeSelect │ │ ├── feat_async_data_load.py │ │ ├── feat_max_count.py │ │ ├── feat_prefix.py │ │ └── fix_read_only.py │ └── AntdUpload │ │ ├── feat_pastable.py │ │ └── fix_follow_theme.py ├── feat_variant_underlined.py ├── feedback │ ├── AntdAlert │ │ └── feat_icon.py │ ├── AntdMessage │ │ └── fix_follow_config_provider.py │ ├── AntdModal │ │ ├── feat_force_render.py │ │ └── feat_responsive_width.py │ ├── AntdNotification │ │ ├── feat_show_progress.py │ │ └── fix_follow_config_provider.py │ ├── AntdPopupCard │ │ └── feat_force_render.py │ └── AntdResult │ │ └── feat_extra.py ├── general │ ├── AntdButton │ │ ├── feat_color_and_variant.py │ │ └── feat_preset_color.py │ ├── AntdFloatButtonGroup │ │ ├── feat_placement.py │ │ └── feat_tooltip.py │ └── AntdIcon │ │ └── feat_iconfont.py ├── layout │ ├── AntdCenter │ │ └── feat_use_token.py │ ├── AntdDivider │ │ ├── feat_plain.py │ │ └── feat_size.py │ └── AntdSplitter │ │ ├── feat_AntdSplitter.py │ │ ├── feat_lazy.py │ │ └── refactor.py ├── navigation │ ├── AntdBreadcrumb │ │ ├── feat_menu_item_event.py │ │ └── refactor_items.py │ ├── AntdDropdown │ │ └── feat_extra.py │ ├── AntdMenu │ │ ├── feat_currentItem.py │ │ ├── feat_currentItemPath.py │ │ ├── feat_currentKeyPath.py │ │ ├── feat_expandIcon.py │ │ ├── feat_triggerSubMenuAction.py │ │ ├── fix_onlyExpandCurrentSubMenu.py │ │ └── fix_with_sider.py │ └── AntdPagination │ │ └── feat_align.py └── other │ ├── AntdAffix │ └── feat_listen_affixed.py │ ├── AntdBackTop │ └── refactor.py │ ├── AntdCopyText │ ├── feat_copy_table.py │ └── feat_tooltips.py │ └── Fragment │ └── feat_use_token.py ├── usage.py ├── webpack.config.js └── webpack.serve.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | /.build_cache 3 | /assets 4 | /build 5 | /deps 6 | /dist 7 | /feffery_antd_components/*.json 8 | /feffery_antd_components/*.js 9 | /feffery_antd_components/*.map 10 | /feffery_antd_components/__pycache__ 11 | /feffery_antd_components.egg-info 12 | /inst 13 | /man 14 | /node_modules 15 | /R 16 | /src/demo 17 | /src/jl 18 | /src/*.jl 19 | .Rbuildignore 20 | package-lock.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | 3 | /.idea 4 | 5 | /build 6 | 7 | /deps 8 | 9 | /dist 10 | 11 | /feffery_antd_components.egg-info 12 | 13 | /inst 14 | 15 | /man 16 | 17 | /.git 18 | 19 | /_* 20 | 21 | /R 22 | 23 | /.vscode 24 | 25 | __pycache__ 26 | 27 | index.html 28 | 29 | package-lock.json 30 | 31 | /.build_cache 32 | 33 | /jl 34 | 35 | FefferyAntdComponents.jl 36 | 37 | .Rbuildignore 38 | 39 | /assets -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING 2 | 3 | This project was generated by the [dash-component-boilerplate](https://github.com/plotly/dash-component-boilerplate) it contains the minimal set of code required to create your own custom Dash component. 4 | 5 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: fefferyAntdComponents 2 | Title: Best implementation of Antd components in Plotly Dash. 3 | Version: 0.4.0-rc6 4 | Description: Best implementation of Antd components in Plotly Dash. 5 | Depends: R (>= 3.0.2) 6 | Imports: 7 | Suggests: 8 | License: MIT + file LICENSE 9 | URL: http://fac.feffery.tech/ 10 | BugReports: https://github.com/CNFeffery/feffery-antd-components/issues 11 | Encoding: UTF-8 12 | LazyData: true 13 | KeepSource: true 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 CNFeffery 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include feffery_antd_components/*.js 2 | include feffery_antd_components/*.map 3 | include *.json 4 | include README.md 5 | include LICENSE 6 | include package.json 7 | -------------------------------------------------------------------------------- /Project.toml: -------------------------------------------------------------------------------- 1 | 2 | name = "FefferyAntdComponents" 3 | uuid = "1b08a953-4be3-4667-9a23-674b58f7de79" 4 | authors = ["CNFeffery "] 5 | version = "0.4.0-rc6" 6 | 7 | [deps] 8 | Dash = "1b08a953-4be3-4667-9a23-3db579824955" 9 | 10 | [compat] 11 | julia = "1.2" 12 | Dash = "0.1.3, 1.0" 13 | -------------------------------------------------------------------------------- /bug_fix.py: -------------------------------------------------------------------------------- 1 | import dash 2 | import feffery_antd_components as fac 3 | from dash import Input, Output, html 4 | 5 | app = dash.Dash(__name__) 6 | 7 | app.layout = html.Div( 8 | [ 9 | fac.AntdDateRangePicker( 10 | id='searchTime', 11 | allowClear=True, 12 | ), 13 | fac.AntdButton( 14 | '重置', 15 | type='primary', 16 | danger=True, 17 | id='reload', 18 | ), 19 | ] 20 | ) 21 | 22 | 23 | @app.callback( 24 | Output('searchTime', 'value'), 25 | Input('reload', 'nClicks'), 26 | prevent_initial_call=True, 27 | ) 28 | def reload(nClicks): 29 | if nClicks: 30 | return [None, None] 31 | 32 | return dash.no_update 33 | 34 | 35 | if __name__ == '__main__': 36 | app.run(debug=True) 37 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdCardGrid.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdCardGrid(Component): 22 | """An AntdCardGrid component. 23 | 卡片网格组件AntdCardGrid 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - children (a list of or a singular dash component, string or number; optional): 34 | 组件型,内嵌元素. 35 | 36 | - className (string | dict; optional): 37 | 当前组件css类名,支持[动态css](/advanced-classname). 38 | 39 | - hoverable (boolean; default True): 40 | 鼠标悬停时是否显示特殊样式 默认值:`True`. 41 | 42 | - nClicks (number; default 0): 43 | 监听当前卡片网格累计点击次数 默认值:`0`. 44 | 45 | - data-* (string; optional): 46 | `data-*`格式属性通配. 47 | 48 | - aria-* (string; optional): 49 | `aria-*`格式属性通配.""" 50 | _children_props = [] 51 | _base_nodes = ['children'] 52 | _namespace = 'feffery_antd_components' 53 | _type = 'AntdCardGrid' 54 | 55 | 56 | def __init__( 57 | self, 58 | children: typing.Optional[ComponentType] = None, 59 | id: typing.Optional[typing.Union[str, dict]] = None, 60 | key: typing.Optional[str] = None, 61 | style: typing.Optional[typing.Any] = None, 62 | className: typing.Optional[typing.Union[str, dict]] = None, 63 | hoverable: typing.Optional[bool] = None, 64 | nClicks: typing.Optional[NumberType] = None, 65 | **kwargs 66 | ): 67 | self._prop_names = ['id', 'key', 'children', 'style', 'className', 'hoverable', 'nClicks', 'data-*', 'aria-*'] 68 | self._valid_wildcard_attributes = ['data-', 'aria-'] 69 | self.available_properties = ['id', 'key', 'children', 'style', 'className', 'hoverable', 'nClicks', 'data-*', 'aria-*'] 70 | self.available_wildcard_properties = ['data-', 'aria-'] 71 | _explicit_args = kwargs.pop('_explicit_args') 72 | _locals = locals() 73 | _locals.update(kwargs) # For wildcard attrs and excess named props 74 | args = {k: _locals[k] for k in _explicit_args if k != 'children'} 75 | 76 | super(AntdCardGrid, self).__init__(children=children, **args) 77 | 78 | setattr(AntdCardGrid, "__init__", _explicitize_args(AntdCardGrid.__init__)) 79 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdCenter.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdCenter(Component): 22 | """An AntdCenter component. 23 | 居中组件AntdCenter 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - children (a list of or a singular dash component, string or number; optional): 34 | 组件型,内嵌元素. 35 | 36 | - className (string | dict; optional): 37 | 当前组件css类名,支持[动态css](/advanced-classname). 38 | 39 | - inline (boolean; default False): 40 | 是否渲染为行内元素 默认值:`False`. 41 | 42 | - inheritStyleToken (boolean; default False): 43 | 是否在背景色、字体颜色、字体大小等样式上联动`AntdConfigProvider`相关设置 默认值:`False`. 44 | 45 | - data-* (string; optional): 46 | `data-*`格式属性通配. 47 | 48 | - aria-* (string; optional): 49 | `aria-*`格式属性通配.""" 50 | _children_props = [] 51 | _base_nodes = ['children'] 52 | _namespace = 'feffery_antd_components' 53 | _type = 'AntdCenter' 54 | 55 | 56 | def __init__( 57 | self, 58 | children: typing.Optional[ComponentType] = None, 59 | id: typing.Optional[typing.Union[str, dict]] = None, 60 | key: typing.Optional[str] = None, 61 | style: typing.Optional[typing.Any] = None, 62 | className: typing.Optional[typing.Union[str, dict]] = None, 63 | inline: typing.Optional[bool] = None, 64 | inheritStyleToken: typing.Optional[bool] = None, 65 | **kwargs 66 | ): 67 | self._prop_names = ['id', 'key', 'children', 'style', 'className', 'inline', 'inheritStyleToken', 'data-*', 'aria-*'] 68 | self._valid_wildcard_attributes = ['data-', 'aria-'] 69 | self.available_properties = ['id', 'key', 'children', 'style', 'className', 'inline', 'inheritStyleToken', 'data-*', 'aria-*'] 70 | self.available_wildcard_properties = ['data-', 'aria-'] 71 | _explicit_args = kwargs.pop('_explicit_args') 72 | _locals = locals() 73 | _locals.update(kwargs) # For wildcard attrs and excess named props 74 | args = {k: _locals[k] for k in _explicit_args if k != 'children'} 75 | 76 | super(AntdCenter, self).__init__(children=children, **args) 77 | 78 | setattr(AntdCenter, "__init__", _explicitize_args(AntdCenter.__init__)) 79 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdContent.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdContent(Component): 22 | """An AntdContent component. 23 | 内容区组件AntdContent 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - children (a list of or a singular dash component, string or number; optional): 34 | 组件型,内嵌元素. 35 | 36 | - className (string | dict; optional): 37 | 当前组件css类名,支持[动态css](/advanced-classname). 38 | 39 | - data-* (string; optional): 40 | `data-*`格式属性通配. 41 | 42 | - aria-* (string; optional): 43 | `aria-*`格式属性通配.""" 44 | _children_props = [] 45 | _base_nodes = ['children'] 46 | _namespace = 'feffery_antd_components' 47 | _type = 'AntdContent' 48 | 49 | 50 | def __init__( 51 | self, 52 | children: typing.Optional[ComponentType] = None, 53 | id: typing.Optional[typing.Union[str, dict]] = None, 54 | key: typing.Optional[str] = None, 55 | style: typing.Optional[typing.Any] = None, 56 | className: typing.Optional[typing.Union[str, dict]] = None, 57 | **kwargs 58 | ): 59 | self._prop_names = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 60 | self._valid_wildcard_attributes = ['data-', 'aria-'] 61 | self.available_properties = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 62 | self.available_wildcard_properties = ['data-', 'aria-'] 63 | _explicit_args = kwargs.pop('_explicit_args') 64 | _locals = locals() 65 | _locals.update(kwargs) # For wildcard attrs and excess named props 66 | args = {k: _locals[k] for k in _explicit_args if k != 'children'} 67 | 68 | super(AntdContent, self).__init__(children=children, **args) 69 | 70 | setattr(AntdContent, "__init__", _explicitize_args(AntdContent.__init__)) 71 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdFooter.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdFooter(Component): 22 | """An AntdFooter component. 23 | 页尾组件AntdFooter 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - children (a list of or a singular dash component, string or number; optional): 34 | 组件型,内嵌元素. 35 | 36 | - className (string | dict; optional): 37 | 当前组件css类名,支持[动态css](/advanced-classname). 38 | 39 | - data-* (string; optional): 40 | `data-*`格式属性通配. 41 | 42 | - aria-* (string; optional): 43 | `aria-*`格式属性通配.""" 44 | _children_props = [] 45 | _base_nodes = ['children'] 46 | _namespace = 'feffery_antd_components' 47 | _type = 'AntdFooter' 48 | 49 | 50 | def __init__( 51 | self, 52 | children: typing.Optional[ComponentType] = None, 53 | id: typing.Optional[typing.Union[str, dict]] = None, 54 | key: typing.Optional[str] = None, 55 | style: typing.Optional[typing.Any] = None, 56 | className: typing.Optional[typing.Union[str, dict]] = None, 57 | **kwargs 58 | ): 59 | self._prop_names = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 60 | self._valid_wildcard_attributes = ['data-', 'aria-'] 61 | self.available_properties = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 62 | self.available_wildcard_properties = ['data-', 'aria-'] 63 | _explicit_args = kwargs.pop('_explicit_args') 64 | _locals = locals() 65 | _locals.update(kwargs) # For wildcard attrs and excess named props 66 | args = {k: _locals[k] for k in _explicit_args if k != 'children'} 67 | 68 | super(AntdFooter, self).__init__(children=children, **args) 69 | 70 | setattr(AntdFooter, "__init__", _explicitize_args(AntdFooter.__init__)) 71 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdHeader.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdHeader(Component): 22 | """An AntdHeader component. 23 | 页首组件AntdHeader 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - children (a list of or a singular dash component, string or number; optional): 34 | 组件型,内嵌元素. 35 | 36 | - className (string | dict; optional): 37 | 当前组件css类名,支持[动态css](/advanced-classname). 38 | 39 | - data-* (string; optional): 40 | `data-*`格式属性通配. 41 | 42 | - aria-* (string; optional): 43 | `aria-*`格式属性通配.""" 44 | _children_props = [] 45 | _base_nodes = ['children'] 46 | _namespace = 'feffery_antd_components' 47 | _type = 'AntdHeader' 48 | 49 | 50 | def __init__( 51 | self, 52 | children: typing.Optional[ComponentType] = None, 53 | id: typing.Optional[typing.Union[str, dict]] = None, 54 | key: typing.Optional[str] = None, 55 | style: typing.Optional[typing.Any] = None, 56 | className: typing.Optional[typing.Union[str, dict]] = None, 57 | **kwargs 58 | ): 59 | self._prop_names = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 60 | self._valid_wildcard_attributes = ['data-', 'aria-'] 61 | self.available_properties = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 62 | self.available_wildcard_properties = ['data-', 'aria-'] 63 | _explicit_args = kwargs.pop('_explicit_args') 64 | _locals = locals() 65 | _locals.update(kwargs) # For wildcard attrs and excess named props 66 | args = {k: _locals[k] for k in _explicit_args if k != 'children'} 67 | 68 | super(AntdHeader, self).__init__(children=children, **args) 69 | 70 | setattr(AntdHeader, "__init__", _explicitize_args(AntdHeader.__init__)) 71 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdLayout.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdLayout(Component): 22 | """An AntdLayout component. 23 | 布局容器组件AntdLayout 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - children (a list of or a singular dash component, string or number; optional): 34 | 组件型,内嵌元素. 35 | 36 | - className (string | dict; optional): 37 | 当前组件css类名,支持[动态css](/advanced-classname). 38 | 39 | - data-* (string; optional): 40 | `data-*`格式属性通配. 41 | 42 | - aria-* (string; optional): 43 | `aria-*`格式属性通配.""" 44 | _children_props = [] 45 | _base_nodes = ['children'] 46 | _namespace = 'feffery_antd_components' 47 | _type = 'AntdLayout' 48 | 49 | 50 | def __init__( 51 | self, 52 | children: typing.Optional[ComponentType] = None, 53 | id: typing.Optional[typing.Union[str, dict]] = None, 54 | key: typing.Optional[str] = None, 55 | style: typing.Optional[typing.Any] = None, 56 | className: typing.Optional[typing.Union[str, dict]] = None, 57 | **kwargs 58 | ): 59 | self._prop_names = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 60 | self._valid_wildcard_attributes = ['data-', 'aria-'] 61 | self.available_properties = ['id', 'key', 'children', 'style', 'className', 'data-*', 'aria-*'] 62 | self.available_wildcard_properties = ['data-', 'aria-'] 63 | _explicit_args = kwargs.pop('_explicit_args') 64 | _locals = locals() 65 | _locals.update(kwargs) # For wildcard attrs and excess named props 66 | args = {k: _locals[k] for k in _explicit_args if k != 'children'} 67 | 68 | super(AntdLayout, self).__init__(children=children, **args) 69 | 70 | setattr(AntdLayout, "__init__", _explicitize_args(AntdLayout.__init__)) 71 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdSkeletonImage.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdSkeletonImage(Component): 22 | """An AntdSkeletonImage component. 23 | 骨骼屏图片占位图组件AntdSkeletonImage 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - className (string | dict; optional): 34 | 当前组件css类名,支持[动态css](/advanced-classname). 35 | 36 | - data-* (string; optional): 37 | `data-*`格式属性通配. 38 | 39 | - aria-* (string; optional): 40 | `aria-*`格式属性通配.""" 41 | _children_props = [] 42 | _base_nodes = ['children'] 43 | _namespace = 'feffery_antd_components' 44 | _type = 'AntdSkeletonImage' 45 | 46 | 47 | def __init__( 48 | self, 49 | id: typing.Optional[typing.Union[str, dict]] = None, 50 | key: typing.Optional[str] = None, 51 | style: typing.Optional[typing.Any] = None, 52 | className: typing.Optional[typing.Union[str, dict]] = None, 53 | **kwargs 54 | ): 55 | self._prop_names = ['id', 'key', 'style', 'className', 'data-*', 'aria-*'] 56 | self._valid_wildcard_attributes = ['data-', 'aria-'] 57 | self.available_properties = ['id', 'key', 'style', 'className', 'data-*', 'aria-*'] 58 | self.available_wildcard_properties = ['data-', 'aria-'] 59 | _explicit_args = kwargs.pop('_explicit_args') 60 | _locals = locals() 61 | _locals.update(kwargs) # For wildcard attrs and excess named props 62 | args = {k: _locals[k] for k in _explicit_args} 63 | 64 | super(AntdSkeletonImage, self).__init__(**args) 65 | 66 | setattr(AntdSkeletonImage, "__init__", _explicitize_args(AntdSkeletonImage.__init__)) 67 | -------------------------------------------------------------------------------- /feffery_antd_components/AntdSkeletonInput.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class AntdSkeletonInput(Component): 22 | """An AntdSkeletonInput component. 23 | 骨骼屏输入框占位图组件AntdSkeletonInput 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - className (string | dict; optional): 34 | 当前组件css类名,支持[动态css](/advanced-classname). 35 | 36 | - active (boolean; default False): 37 | 是否显示动画 默认值:`False`. 38 | 39 | - size (a value equal to: 'large', 'small', 'default'; default 'default'): 40 | 输入框占位图尺寸,可选项有`'large'`、`'small'`、`'default'` 默认值:`'default'`. 41 | 42 | - data-* (string; optional): 43 | `data-*`格式属性通配. 44 | 45 | - aria-* (string; optional): 46 | `aria-*`格式属性通配.""" 47 | _children_props = [] 48 | _base_nodes = ['children'] 49 | _namespace = 'feffery_antd_components' 50 | _type = 'AntdSkeletonInput' 51 | 52 | 53 | def __init__( 54 | self, 55 | id: typing.Optional[typing.Union[str, dict]] = None, 56 | key: typing.Optional[str] = None, 57 | style: typing.Optional[typing.Any] = None, 58 | className: typing.Optional[typing.Union[str, dict]] = None, 59 | active: typing.Optional[bool] = None, 60 | size: typing.Optional[Literal["large", "small", "default"]] = None, 61 | **kwargs 62 | ): 63 | self._prop_names = ['id', 'key', 'style', 'className', 'active', 'size', 'data-*', 'aria-*'] 64 | self._valid_wildcard_attributes = ['data-', 'aria-'] 65 | self.available_properties = ['id', 'key', 'style', 'className', 'active', 'size', 'data-*', 'aria-*'] 66 | self.available_wildcard_properties = ['data-', 'aria-'] 67 | _explicit_args = kwargs.pop('_explicit_args') 68 | _locals = locals() 69 | _locals.update(kwargs) # For wildcard attrs and excess named props 70 | args = {k: _locals[k] for k in _explicit_args} 71 | 72 | super(AntdSkeletonInput, self).__init__(**args) 73 | 74 | setattr(AntdSkeletonInput, "__init__", _explicitize_args(AntdSkeletonInput.__init__)) 75 | -------------------------------------------------------------------------------- /feffery_antd_components/Fragment.py: -------------------------------------------------------------------------------- 1 | # AUTO GENERATED FILE - DO NOT EDIT 2 | 3 | import typing # noqa: F401 4 | from typing_extensions import TypedDict, NotRequired, Literal # noqa: F401 5 | from dash.development.base_component import Component, _explicitize_args 6 | 7 | ComponentType = typing.Union[ 8 | str, 9 | int, 10 | float, 11 | Component, 12 | None, 13 | typing.Sequence[typing.Union[str, int, float, Component, None]], 14 | ] 15 | 16 | NumberType = typing.Union[ 17 | typing.SupportsFloat, typing.SupportsInt, typing.SupportsComplex 18 | ] 19 | 20 | 21 | class Fragment(Component): 22 | """A Fragment component. 23 | 空节点组件Fragment 24 | 25 | Keyword arguments: 26 | 27 | - id (string; optional): 28 | 组件唯一id. 29 | 30 | - key (string; optional): 31 | 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果. 32 | 33 | - children (a list of or a singular dash component, string or number; optional): 34 | 组件型,内嵌元素. 35 | 36 | - token (dict; optional): 37 | 监听当前组件所在作用范围对应的样式`token`参数,需配合上层`AntdConfigProvider`组件使用.""" 38 | _children_props = [] 39 | _base_nodes = ['children'] 40 | _namespace = 'feffery_antd_components' 41 | _type = 'Fragment' 42 | 43 | 44 | def __init__( 45 | self, 46 | children: typing.Optional[ComponentType] = None, 47 | id: typing.Optional[typing.Union[str, dict]] = None, 48 | key: typing.Optional[str] = None, 49 | token: typing.Optional[dict] = None, 50 | **kwargs 51 | ): 52 | self._prop_names = ['id', 'key', 'children', 'token'] 53 | self._valid_wildcard_attributes = [] 54 | self.available_properties = ['id', 'key', 'children', 'token'] 55 | self.available_wildcard_properties = [] 56 | _explicit_args = kwargs.pop('_explicit_args') 57 | _locals = locals() 58 | _locals.update(kwargs) # For wildcard attrs and excess named props 59 | args = {k: _locals[k] for k in _explicit_args if k != 'children'} 60 | 61 | super(Fragment, self).__init__(children=children, **args) 62 | 63 | setattr(Fragment, "__init__", _explicitize_args(Fragment.__init__)) 64 | -------------------------------------------------------------------------------- /feffery_antd_components/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function as _ 2 | 3 | import os as _os 4 | import sys as _sys 5 | import json 6 | 7 | import dash as _dash 8 | 9 | # noinspection PyUnresolvedReferences 10 | from ._imports_ import * # noqa: F403 11 | from ._imports_ import __all__ 12 | 13 | if not hasattr(_dash, '__plotly_dash') and not hasattr(_dash, 'development'): 14 | print('Dash was not successfully imported. ' 15 | 'Make sure you don\'t have a file ' 16 | 'named \n"dash.py" in your current directory.', file=_sys.stderr) 17 | _sys.exit(1) 18 | 19 | _basepath = _os.path.dirname(__file__) 20 | _filepath = _os.path.abspath(_os.path.join(_basepath, 'package-info.json')) 21 | with open(_filepath) as f: 22 | package = json.load(f) 23 | 24 | package_name = package['name'].replace(' ', '_').replace('-', '_') 25 | __version__ = package['version'] 26 | 27 | _current_path = _os.path.dirname(_os.path.abspath(__file__)) 28 | 29 | _this_module = _sys.modules[__name__] 30 | 31 | async_resources = [ 32 | 'antd_table', 33 | 'upload', 34 | 'data_entry', 35 | 'data_display', 36 | ] 37 | 38 | 39 | _js_dist = [ 40 | { 41 | 'relative_package_path': 'feffery_antd_components.min.js', 42 | 'external_url': 'https://unpkg.com/{0}@{2}/{1}/{1}.min.js'.format( 43 | package_name, __name__, __version__), 44 | 'namespace': package_name 45 | }, 46 | { 47 | 'relative_package_path': 'feffery_antd_components.min.js.map', 48 | 'external_url': 'https://unpkg.com/{0}@{2}/{1}/{1}.min.js.map'.format( 49 | package_name, __name__, __version__), 50 | 'namespace': package_name, 51 | 'dynamic': True 52 | } 53 | ] 54 | 55 | _js_dist.extend( 56 | [ 57 | { 58 | "relative_package_path": "async-{}.js".format(async_resource), 59 | "external_url": ("https://unpkg.com/{0}@{2}" "/{1}/async-{3}.js").format( 60 | package_name, __name__, __version__, async_resource 61 | ), 62 | "namespace": package_name, 63 | "async": True, 64 | } 65 | for async_resource in async_resources 66 | ] 67 | ) 68 | 69 | _js_dist.extend( 70 | [ 71 | { 72 | "relative_package_path": "async-{}.js.map".format(async_resource), 73 | "external_url": ("https://unpkg.com/{0}@{2}" "/{1}/async-{3}.js.map").format( 74 | package_name, __name__, __version__, async_resource 75 | ), 76 | "namespace": package_name, 77 | 'dynamic': True 78 | } 79 | for async_resource in async_resources 80 | ] 81 | ) 82 | 83 | _css_dist = [] 84 | 85 | 86 | for _component in __all__: 87 | setattr(locals()[_component], '_js_dist', _js_dist) 88 | setattr(locals()[_component], '_css_dist', _css_dist) 89 | -------------------------------------------------------------------------------- /images/公众号.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CNFeffery/feffery-antd-components/adfc226223c02db374a20875db9ca0d3f57745d8/images/公众号.png -------------------------------------------------------------------------------- /images/国际化示例_de-de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CNFeffery/feffery-antd-components/adfc226223c02db374a20875db9ca0d3f57745d8/images/国际化示例_de-de.png -------------------------------------------------------------------------------- /images/国际化示例_en-us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CNFeffery/feffery-antd-components/adfc226223c02db374a20875db9ca0d3f57745d8/images/国际化示例_en-us.png -------------------------------------------------------------------------------- /images/知识星球.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CNFeffery/feffery-antd-components/adfc226223c02db374a20875db9ca0d3f57745d8/images/知识星球.jpg -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | testpaths = tests/ 3 | addopts = -rsxX -vv 4 | log_format = %(asctime)s | %(levelname)s | %(name)s:%(lineno)d | %(message)s 5 | log_cli_level = ERROR 6 | -------------------------------------------------------------------------------- /release-to-test-pypi.sh: -------------------------------------------------------------------------------- 1 | python setup.py sdist bdist_wheel && python -m twine upload --repository-url https://test.pypi.org/legacy/ dist/* 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # dash is required to call `build:py` 2 | dash[dev]>=1.15.0 3 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | line-length = 60 2 | 3 | [format] 4 | quote-style = "single" 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import io 2 | import json 3 | from setuptools import setup 4 | 5 | 6 | with open('package.json') as f: 7 | package = json.load(f) 8 | 9 | package_name = package["name"].replace(" ", "_").replace("-", "_") 10 | 11 | setup( 12 | name=package_name, 13 | version=package["version"], 14 | author_email=package['email'], 15 | homepage='https://github.com/CNFeffery/feffery-antd-components', 16 | author=package['author'], 17 | packages=[package_name], 18 | include_package_data=True, 19 | package_data={ 20 | 'feffery_antd_components': ['*'] 21 | }, 22 | license=package['license'], 23 | description=package.get('description', package_name), 24 | long_description=io.open("README.md", encoding="utf-8").read(), 25 | long_description_content_type="text/markdown", 26 | install_requires=[ 27 | 'dash>=3.0.4', 28 | ], 29 | classifiers=[ 30 | 'Framework :: Dash', 31 | ], 32 | url='https://github.com/CNFeffery/feffery-antd-components' 33 | ) 34 | -------------------------------------------------------------------------------- /src/lib/components/dataDisplay/AntdCheckableTag.react.js: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const LazyAntdCheckableTag = React.lazy(() => import(/* webpackChunkName: "data_display" */ '../../fragments/dataDisplay/AntdCheckableTag.react')); 5 | 6 | /** 7 | * 可选择标签AntdCheckableTag 8 | */ 9 | const AntdCheckableTag = ({ 10 | id, 11 | className, 12 | style, 13 | key, 14 | content, 15 | checkedContent, 16 | unCheckedContent, 17 | checked = false, 18 | setProps, 19 | ...others 20 | }) => { 21 | return ( 22 | 23 | 37 | 38 | ); 39 | } 40 | 41 | AntdCheckableTag.propTypes = { 42 | /** 43 | * 组件唯一id 44 | */ 45 | id: PropTypes.string, 46 | 47 | /** 48 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 49 | */ 50 | key: PropTypes.string, 51 | 52 | /** 53 | * 当前组件css样式 54 | */ 55 | style: PropTypes.object, 56 | 57 | /** 58 | * 当前组件css类名,支持[动态css](/advanced-classname) 59 | */ 60 | className: PropTypes.oneOfType([ 61 | PropTypes.string, 62 | PropTypes.object 63 | ]), 64 | 65 | /** 66 | * 组件型,标签内容 67 | */ 68 | content: PropTypes.node, 69 | 70 | /** 71 | * 组件型,选择状态下的标签内容 72 | */ 73 | checkedContent: PropTypes.node, 74 | 75 | /** 76 | * 组件型,未选择状态下的标签内容 77 | */ 78 | unCheckedContent: PropTypes.node, 79 | 80 | /** 81 | * 监听或设置当前标签的选择状态 82 | * 默认值:`false` 83 | */ 84 | checked: PropTypes.bool, 85 | 86 | /** 87 | * `data-*`格式属性通配 88 | */ 89 | 'data-*': PropTypes.string, 90 | 91 | /** 92 | * `aria-*`格式属性通配 93 | */ 94 | 'aria-*': PropTypes.string, 95 | 96 | /** 97 | * Dash-assigned callback that should be called to report property changes 98 | * to Dash, to make them available for callbacks. 99 | */ 100 | setProps: PropTypes.func 101 | }; 102 | 103 | export default AntdCheckableTag; 104 | 105 | export const propTypes = AntdCheckableTag.propTypes; 106 | export const defaultProps = AntdCheckableTag.defaultProps; -------------------------------------------------------------------------------- /src/lib/components/dataDisplay/AntdRibbon.react.js: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const LazyAntdRibbon = React.lazy(() => import(/* webpackChunkName: "data_display" */ '../../fragments/dataDisplay/AntdRibbon.react')); 5 | 6 | /** 7 | * 缎带组件AntdRibbon 8 | */ 9 | const AntdRibbon = ({ 10 | id, 11 | children, 12 | className, 13 | style, 14 | key, 15 | color, 16 | placement = 'end', 17 | text, 18 | setProps, 19 | ...others 20 | }) => { 21 | return ( 22 | 23 | 37 | 38 | ); 39 | } 40 | 41 | AntdRibbon.propTypes = { 42 | /** 43 | * 组件唯一id 44 | */ 45 | id: PropTypes.string, 46 | 47 | /** 48 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 49 | */ 50 | key: PropTypes.string, 51 | 52 | /** 53 | * 组件型,添加徽标的目标元素 54 | */ 55 | children: PropTypes.node, 56 | 57 | /** 58 | * 当前组件css样式 59 | */ 60 | style: PropTypes.object, 61 | 62 | /** 63 | * 当前组件css类名,支持[动态css](/advanced-classname) 64 | */ 65 | className: PropTypes.oneOfType([ 66 | PropTypes.string, 67 | PropTypes.object 68 | ]), 69 | 70 | /** 71 | * 缎带颜色 72 | */ 73 | color: PropTypes.string, 74 | 75 | /** 76 | * 缎带显示位置,可选项有`'start'`、`'end'` 77 | * 默认值:`'end'` 78 | */ 79 | placement: PropTypes.oneOf(['start', 'end']), 80 | 81 | /** 82 | * 组件型,缎带内容 83 | */ 84 | text: PropTypes.node, 85 | 86 | /** 87 | * `data-*`格式属性通配 88 | */ 89 | 'data-*': PropTypes.string, 90 | 91 | /** 92 | * `aria-*`格式属性通配 93 | */ 94 | 'aria-*': PropTypes.string, 95 | 96 | /** 97 | * Dash-assigned callback that should be called to report property changes 98 | * to Dash, to make them available for callbacks. 99 | */ 100 | setProps: PropTypes.func 101 | }; 102 | 103 | export default AntdRibbon; 104 | 105 | export const propTypes = AntdRibbon.propTypes; 106 | export const defaultProps = AntdRibbon.defaultProps; -------------------------------------------------------------------------------- /src/lib/components/dataDisplay/card/AntdCardGrid.react.js: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const LazyAntdCardGrid = React.lazy(() => import(/* webpackChunkName: "data_display" */ '../../../fragments/dataDisplay/card/AntdCardGrid.react')); 5 | 6 | /** 7 | * 卡片网格组件AntdCardGrid 8 | */ 9 | const AntdCardGrid = ({ 10 | id, 11 | children, 12 | className, 13 | style, 14 | key, 15 | hoverable = true, 16 | nClicks = 0, 17 | setProps, 18 | ...others 19 | }) => { 20 | return ( 21 | 22 | 35 | 36 | ); 37 | } 38 | 39 | AntdCardGrid.propTypes = { 40 | /** 41 | * 组件唯一id 42 | */ 43 | id: PropTypes.string, 44 | 45 | /** 46 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 47 | */ 48 | key: PropTypes.string, 49 | 50 | /** 51 | * 组件型,内嵌元素 52 | */ 53 | children: PropTypes.node, 54 | 55 | /** 56 | * 当前组件css样式 57 | */ 58 | style: PropTypes.object, 59 | 60 | /** 61 | * 当前组件css类名,支持[动态css](/advanced-classname) 62 | */ 63 | className: PropTypes.oneOfType([ 64 | PropTypes.string, 65 | PropTypes.object 66 | ]), 67 | 68 | /** 69 | * 鼠标悬停时是否显示特殊样式 70 | * 默认值:`true` 71 | */ 72 | hoverable: PropTypes.bool, 73 | 74 | /** 75 | * 监听当前卡片网格累计点击次数 76 | * 默认值:`0` 77 | */ 78 | nClicks: PropTypes.number, 79 | 80 | /** 81 | * `data-*`格式属性通配 82 | */ 83 | 'data-*': PropTypes.string, 84 | 85 | /** 86 | * `aria-*`格式属性通配 87 | */ 88 | 'aria-*': PropTypes.string, 89 | 90 | /** 91 | * Dash-assigned callback that should be called to report property changes 92 | * to Dash, to make them available for callbacks. 93 | */ 94 | setProps: PropTypes.func 95 | }; 96 | 97 | export default AntdCardGrid; 98 | 99 | export const propTypes = AntdCardGrid.propTypes; 100 | export const defaultProps = AntdCardGrid.defaultProps; -------------------------------------------------------------------------------- /src/lib/components/dataDisplay/card/AntdCardMeta.react.js: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const LazyAntdCardMeta = React.lazy(() => import(/* webpackChunkName: "data_display" */ '../../../fragments/dataDisplay/card/AntdCardMeta.react')); 5 | 6 | /** 7 | * 结构化卡片组件AntdCardMeta 8 | */ 9 | const AntdCardMeta = ({ 10 | id, 11 | className, 12 | style, 13 | key, 14 | avatar, 15 | description, 16 | title, 17 | setProps, 18 | ...others 19 | }) => { 20 | return ( 21 | 22 | 35 | 36 | ); 37 | } 38 | 39 | AntdCardMeta.propTypes = { 40 | /** 41 | * 组件唯一id 42 | */ 43 | id: PropTypes.string, 44 | 45 | /** 46 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 47 | */ 48 | key: PropTypes.string, 49 | 50 | /** 51 | * 当前组件css样式 52 | */ 53 | style: PropTypes.object, 54 | 55 | /** 56 | * 当前组件css类名,支持[动态css](/advanced-classname) 57 | */ 58 | className: PropTypes.oneOfType([ 59 | PropTypes.string, 60 | PropTypes.object 61 | ]), 62 | 63 | /** 64 | * 组件型,头像元素 65 | */ 66 | avatar: PropTypes.node, 67 | 68 | /** 69 | * 组件型,描述内容 70 | */ 71 | description: PropTypes.node, 72 | 73 | /** 74 | * 组件型,标题内容 75 | */ 76 | title: PropTypes.node, 77 | 78 | /** 79 | * `data-*`格式属性通配 80 | */ 81 | 'data-*': PropTypes.string, 82 | 83 | /** 84 | * `aria-*`格式属性通配 85 | */ 86 | 'aria-*': PropTypes.string, 87 | 88 | /** 89 | * Dash-assigned callback that should be called to report property changes 90 | * to Dash, to make them available for callbacks. 91 | */ 92 | setProps: PropTypes.func 93 | }; 94 | 95 | export default AntdCardMeta; 96 | 97 | export const propTypes = AntdCardMeta.propTypes; 98 | export const defaultProps = AntdCardMeta.defaultProps; -------------------------------------------------------------------------------- /src/lib/components/feedback/skeleton/AntdSkeletonImage.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | // antd核心 5 | import { Skeleton } from 'antd'; 6 | // 辅助库 7 | import { isString } from 'lodash'; 8 | import { pickBy } from 'ramda'; 9 | import { useLoading } from '../../utils'; 10 | // 自定义hooks 11 | import useCss from '../../../hooks/useCss'; 12 | 13 | /** 14 | * 骨骼屏图片占位图组件AntdSkeletonImage 15 | */ 16 | const AntdSkeletonImage = ({ 17 | id, 18 | style, 19 | className, 20 | key, 21 | setProps, 22 | ...others 23 | }) => { 24 | 25 | return ( 26 | k.startsWith('data-') || k.startsWith('aria-'), others)} 29 | id={id} 30 | style={style} 31 | className={ 32 | isString(className) ? 33 | className : 34 | (className ? useCss(className) : undefined) 35 | } 36 | key={key} 37 | data-dash-is-loading={useLoading()} 38 | /> 39 | ); 40 | } 41 | 42 | AntdSkeletonImage.propTypes = { 43 | /** 44 | * 组件唯一id 45 | */ 46 | id: PropTypes.string, 47 | 48 | /** 49 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 50 | */ 51 | key: PropTypes.string, 52 | 53 | /** 54 | * 当前组件css样式 55 | */ 56 | style: PropTypes.object, 57 | 58 | /** 59 | * 当前组件css类名,支持[动态css](/advanced-classname) 60 | */ 61 | className: PropTypes.oneOfType([ 62 | PropTypes.string, 63 | PropTypes.object 64 | ]), 65 | 66 | /** 67 | * `data-*`格式属性通配 68 | */ 69 | 'data-*': PropTypes.string, 70 | 71 | /** 72 | * `aria-*`格式属性通配 73 | */ 74 | 'aria-*': PropTypes.string, 75 | 76 | /** 77 | * Dash-assigned callback that should be called to report property changes 78 | * to Dash, to make them available for callbacks. 79 | */ 80 | setProps: PropTypes.func 81 | }; 82 | 83 | export default AntdSkeletonImage; -------------------------------------------------------------------------------- /src/lib/components/feedback/skeleton/AntdSkeletonInput.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | // antd核心 5 | import { Skeleton } from 'antd'; 6 | // 辅助库 7 | import { isString } from 'lodash'; 8 | import { pickBy } from 'ramda'; 9 | import { useLoading } from '../../utils'; 10 | // 自定义hooks 11 | import useCss from '../../../hooks/useCss'; 12 | 13 | /** 14 | * 骨骼屏输入框占位图组件AntdSkeletonInput 15 | */ 16 | const AntdSkeletonInput = ({ 17 | id, 18 | style, 19 | className, 20 | key, 21 | active = false, 22 | size = 'default', 23 | setProps, 24 | ...others 25 | }) => { 26 | 27 | return ( 28 | k.startsWith('data-') || k.startsWith('aria-'), others)} 31 | id={id} 32 | style={style} 33 | className={ 34 | isString(className) ? 35 | className : 36 | (className ? useCss(className) : undefined) 37 | } 38 | key={key} 39 | active={active} 40 | size={size} 41 | data-dash-is-loading={useLoading()} 42 | /> 43 | ); 44 | } 45 | 46 | AntdSkeletonInput.propTypes = { 47 | /** 48 | * 组件唯一id 49 | */ 50 | id: PropTypes.string, 51 | 52 | /** 53 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 54 | */ 55 | key: PropTypes.string, 56 | 57 | /** 58 | * 当前组件css样式 59 | */ 60 | style: PropTypes.object, 61 | 62 | /** 63 | * 当前组件css类名,支持[动态css](/advanced-classname) 64 | */ 65 | className: PropTypes.oneOfType([ 66 | PropTypes.string, 67 | PropTypes.object 68 | ]), 69 | 70 | /** 71 | * 是否显示动画 72 | * 默认值:`false` 73 | */ 74 | active: PropTypes.bool, 75 | 76 | /** 77 | * 输入框占位图尺寸,可选项有`'large'`、`'small'`、`'default'` 78 | * 默认值:`'default'` 79 | */ 80 | size: PropTypes.oneOf(['large', 'small', 'default']), 81 | 82 | /** 83 | * `data-*`格式属性通配 84 | */ 85 | 'data-*': PropTypes.string, 86 | 87 | /** 88 | * `aria-*`格式属性通配 89 | */ 90 | 'aria-*': PropTypes.string, 91 | 92 | /** 93 | * Dash-assigned callback that should be called to report property changes 94 | * to Dash, to make them available for callbacks. 95 | */ 96 | setProps: PropTypes.func 97 | }; 98 | 99 | export default AntdSkeletonInput; -------------------------------------------------------------------------------- /src/lib/components/layout/AntdCompact.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import PropTypes from 'prop-types'; 3 | // antd核心 4 | import { Space } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { parseChildrenToArray, useLoading } from '../utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | 12 | const { Compact } = Space; 13 | 14 | /** 15 | * 紧凑排列组件AntdCompact 16 | */ 17 | const AntdCompact = ({ 18 | id, 19 | children, 20 | className, 21 | style, 22 | key, 23 | direction = 'horizontal', 24 | block = false, 25 | setProps, 26 | ...others 27 | }) => { 28 | 29 | children = parseChildrenToArray(children) 30 | 31 | return ( 32 | k.startsWith('data-') || k.startsWith('aria-'), others)} 35 | id={id} 36 | className={ 37 | isString(className) ? 38 | className : 39 | (className ? useCss(className) : undefined) 40 | } 41 | style={style} 42 | key={key} 43 | direction={direction} 44 | block={block} 45 | data-dash-is-loading={useLoading()}> 46 | {children} 47 | 48 | ); 49 | } 50 | 51 | AntdCompact.propTypes = { 52 | /** 53 | * 组件唯一id 54 | */ 55 | id: PropTypes.string, 56 | 57 | /** 58 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 59 | */ 60 | key: PropTypes.string, 61 | 62 | /** 63 | * 组件型,内嵌元素 64 | */ 65 | children: PropTypes.node, 66 | 67 | /** 68 | * 当前组件css样式 69 | */ 70 | style: PropTypes.object, 71 | 72 | /** 73 | * 当前组件css类名,支持[动态css](/advanced-classname) 74 | */ 75 | className: PropTypes.oneOfType([ 76 | PropTypes.string, 77 | PropTypes.object 78 | ]), 79 | 80 | /** 81 | * 排列方向,可选项有`'vertical'`、`'horizontal'` 82 | * 默认值:`'horizontal'` 83 | */ 84 | direction: PropTypes.oneOf(['vertical', 'horizontal']), 85 | 86 | /** 87 | * 是否渲染为块级元素(宽度撑满父容器) 88 | * 默认值:`false` 89 | */ 90 | block: PropTypes.bool, 91 | 92 | /** 93 | * `data-*`格式属性通配 94 | */ 95 | 'data-*': PropTypes.string, 96 | 97 | /** 98 | * `aria-*`格式属性通配 99 | */ 100 | 'aria-*': PropTypes.string, 101 | 102 | /** 103 | * Dash-assigned callback that should be called to report property changes 104 | * to Dash, to make them available for callbacks. 105 | */ 106 | setProps: PropTypes.func 107 | }; 108 | 109 | export default AntdCompact; -------------------------------------------------------------------------------- /src/lib/components/layout/AntdContent.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import PropTypes from 'prop-types'; 3 | // antd核心 4 | import { Layout } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { parseChildrenToArray, useLoading } from '../utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | 12 | const { Content } = Layout; 13 | 14 | /** 15 | * 内容区组件AntdContent 16 | */ 17 | const AntdContent = ({ 18 | id, 19 | children, 20 | className, 21 | style, 22 | key, 23 | setProps, 24 | ...others 25 | }) => { 26 | 27 | children = parseChildrenToArray(children) 28 | 29 | return ( 30 | k.startsWith('data-') || k.startsWith('aria-'), others)} 33 | id={id} 34 | className={ 35 | isString(className) ? 36 | className : 37 | (className ? useCss(className) : undefined) 38 | } 39 | style={style} 40 | key={key} 41 | data-dash-is-loading={useLoading()}> 42 | {children} 43 | 44 | ); 45 | } 46 | 47 | AntdContent.propTypes = { 48 | /** 49 | * 组件唯一id 50 | */ 51 | id: PropTypes.string, 52 | 53 | /** 54 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 55 | */ 56 | key: PropTypes.string, 57 | 58 | /** 59 | * 组件型,内嵌元素 60 | */ 61 | children: PropTypes.node, 62 | 63 | /** 64 | * 当前组件css样式 65 | */ 66 | style: PropTypes.object, 67 | 68 | /** 69 | * 当前组件css类名,支持[动态css](/advanced-classname) 70 | */ 71 | className: PropTypes.oneOfType([ 72 | PropTypes.string, 73 | PropTypes.object 74 | ]), 75 | 76 | /** 77 | * `data-*`格式属性通配 78 | */ 79 | 'data-*': PropTypes.string, 80 | 81 | /** 82 | * `aria-*`格式属性通配 83 | */ 84 | 'aria-*': PropTypes.string, 85 | 86 | /** 87 | * Dash-assigned callback that should be called to report property changes 88 | * to Dash, to make them available for callbacks. 89 | */ 90 | setProps: PropTypes.func 91 | }; 92 | 93 | export default AntdContent; -------------------------------------------------------------------------------- /src/lib/components/layout/AntdFooter.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import PropTypes from 'prop-types'; 3 | // antd核心 4 | import { Layout } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { parseChildrenToArray, useLoading } from '../utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | 12 | const { Footer } = Layout; 13 | 14 | /** 15 | * 页尾组件AntdFooter 16 | */ 17 | const AntdFooter = ({ 18 | id, 19 | children, 20 | className, 21 | style, 22 | key, 23 | setProps, 24 | ...others 25 | }) => { 26 | 27 | children = parseChildrenToArray(children) 28 | 29 | return ( 30 |
k.startsWith('data-') || k.startsWith('aria-'), others)} 33 | id={id} 34 | className={ 35 | isString(className) ? 36 | className : 37 | (className ? useCss(className) : undefined) 38 | } 39 | style={style} 40 | key={key} 41 | data-dash-is-loading={useLoading()}> 42 | {children} 43 |
44 | ); 45 | } 46 | 47 | AntdFooter.propTypes = { 48 | /** 49 | * 组件唯一id 50 | */ 51 | id: PropTypes.string, 52 | 53 | /** 54 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 55 | */ 56 | key: PropTypes.string, 57 | 58 | /** 59 | * 组件型,内嵌元素 60 | */ 61 | children: PropTypes.node, 62 | 63 | /** 64 | * 当前组件css样式 65 | */ 66 | style: PropTypes.object, 67 | 68 | /** 69 | * 当前组件css类名,支持[动态css](/advanced-classname) 70 | */ 71 | className: PropTypes.oneOfType([ 72 | PropTypes.string, 73 | PropTypes.object 74 | ]), 75 | 76 | /** 77 | * `data-*`格式属性通配 78 | */ 79 | 'data-*': PropTypes.string, 80 | 81 | /** 82 | * `aria-*`格式属性通配 83 | */ 84 | 'aria-*': PropTypes.string, 85 | 86 | /** 87 | * Dash-assigned callback that should be called to report property changes 88 | * to Dash, to make them available for callbacks. 89 | */ 90 | setProps: PropTypes.func 91 | }; 92 | 93 | export default AntdFooter; -------------------------------------------------------------------------------- /src/lib/components/layout/AntdHeader.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import PropTypes from 'prop-types'; 3 | // antd核心 4 | import { Layout } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { parseChildrenToArray, useLoading } from '../utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | 12 | const { Header } = Layout; 13 | 14 | /** 15 | * 页首组件AntdHeader 16 | */ 17 | const AntdHeader = ({ 18 | id, 19 | children, 20 | className, 21 | style, 22 | key, 23 | setProps, 24 | ...others 25 | }) => { 26 | 27 | children = parseChildrenToArray(children) 28 | 29 | return ( 30 |
k.startsWith('data-') || k.startsWith('aria-'), others)} 33 | id={id} 34 | className={ 35 | isString(className) ? 36 | className : 37 | (className ? useCss(className) : undefined) 38 | } 39 | style={style} 40 | key={key} 41 | data-dash-is-loading={useLoading()}> 42 | {children} 43 |
44 | ); 45 | } 46 | 47 | AntdHeader.propTypes = { 48 | /** 49 | * 组件唯一id 50 | */ 51 | id: PropTypes.string, 52 | 53 | /** 54 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 55 | */ 56 | key: PropTypes.string, 57 | 58 | /** 59 | * 组件型,内嵌元素 60 | */ 61 | children: PropTypes.node, 62 | 63 | /** 64 | * 当前组件css样式 65 | */ 66 | style: PropTypes.object, 67 | 68 | /** 69 | * 当前组件css类名,支持[动态css](/advanced-classname) 70 | */ 71 | className: PropTypes.oneOfType([ 72 | PropTypes.string, 73 | PropTypes.object 74 | ]), 75 | 76 | /** 77 | * `data-*`格式属性通配 78 | */ 79 | 'data-*': PropTypes.string, 80 | 81 | /** 82 | * `aria-*`格式属性通配 83 | */ 84 | 'aria-*': PropTypes.string, 85 | 86 | /** 87 | * Dash-assigned callback that should be called to report property changes 88 | * to Dash, to make them available for callbacks. 89 | */ 90 | setProps: PropTypes.func 91 | }; 92 | 93 | export default AntdHeader; -------------------------------------------------------------------------------- /src/lib/components/layout/AntdLayout.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import PropTypes from 'prop-types'; 3 | // antd核心 4 | import { Layout } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { parseChildrenToArray, useLoading } from '../utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | 12 | /** 13 | * 布局容器组件AntdLayout 14 | */ 15 | const AntdLayout = ({ 16 | id, 17 | children, 18 | className, 19 | style, 20 | key, 21 | setProps, 22 | ...others 23 | }) => { 24 | 25 | children = parseChildrenToArray(children) 26 | 27 | return ( 28 | k.startsWith('data-') || k.startsWith('aria-'), others)} 31 | id={id} 32 | className={ 33 | isString(className) ? 34 | className : 35 | (className ? useCss(className) : undefined) 36 | } 37 | style={style} 38 | key={key} 39 | data-dash-is-loading={useLoading()}> 40 | {children} 41 | 42 | ); 43 | } 44 | 45 | AntdLayout.propTypes = { 46 | /** 47 | * 组件唯一id 48 | */ 49 | id: PropTypes.string, 50 | 51 | /** 52 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 53 | */ 54 | key: PropTypes.string, 55 | 56 | /** 57 | * 组件型,内嵌元素 58 | */ 59 | children: PropTypes.node, 60 | 61 | /** 62 | * 当前组件css样式 63 | */ 64 | style: PropTypes.object, 65 | 66 | /** 67 | * 当前组件css类名,支持[动态css](/advanced-classname) 68 | */ 69 | className: PropTypes.oneOfType([ 70 | PropTypes.string, 71 | PropTypes.object 72 | ]), 73 | 74 | /** 75 | * `data-*`格式属性通配 76 | */ 77 | 'data-*': PropTypes.string, 78 | 79 | /** 80 | * `aria-*`格式属性通配 81 | */ 82 | 'aria-*': PropTypes.string, 83 | 84 | /** 85 | * Dash-assigned callback that should be called to report property changes 86 | * to Dash, to make them available for callbacks. 87 | */ 88 | setProps: PropTypes.func 89 | }; 90 | 91 | export default AntdLayout; -------------------------------------------------------------------------------- /src/lib/components/other/Fragment.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React, { useEffect } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | // antd核心 5 | import { theme } from 'antd'; 6 | 7 | const { useToken } = theme; 8 | 9 | /** 10 | * 空节点组件Fragment 11 | */ 12 | const Fragment = (props) => { 13 | 14 | const { token: _token } = useToken(); 15 | 16 | useEffect(() => { 17 | props.setProps({ token: _token }); 18 | }, [_token]) 19 | 20 | return (<>{props.children}); 21 | }; 22 | 23 | Fragment.propTypes = { 24 | /** 25 | * 组件唯一id 26 | */ 27 | id: PropTypes.string, 28 | 29 | /** 30 | * 对当前组件的`key`值进行更新,可实现强制重绘当前组件的效果 31 | */ 32 | key: PropTypes.string, 33 | 34 | /** 35 | * 组件型,内嵌元素 36 | */ 37 | children: PropTypes.node, 38 | 39 | /** 40 | * 监听当前组件所在作用范围对应的样式`token`参数,需配合上层`AntdConfigProvider`组件使用 41 | */ 42 | token: PropTypes.object, 43 | 44 | /** 45 | * Dash-assigned callback that should be called to report property changes 46 | * to Dash, to make them available for callbacks. 47 | */ 48 | setProps: PropTypes.func 49 | }; 50 | 51 | export default Fragment; -------------------------------------------------------------------------------- /src/lib/components/utils.js: -------------------------------------------------------------------------------- 1 | import { cloneDeep, isUndefined } from 'lodash'; 2 | import { toPairs, flatten } from 'ramda'; 3 | 4 | const flatToTree = (rawFlat) => { 5 | if (rawFlat) { 6 | let temp = cloneDeep(rawFlat) 7 | let parents = temp.filter((item) => isUndefined(item.parent)) 8 | let children = temp.filter((item) => item.parent) 9 | 10 | children.forEach((item) => { 11 | let currentNode = temp.find((node) => node.key === item.parent) 12 | 13 | currentNode && (currentNode.children ? currentNode.children.push(item) : currentNode.children = [item]) 14 | }); 15 | return parents; 16 | } 17 | return rawFlat; 18 | } 19 | 20 | const parseChildrenToArray = children => { 21 | if (children && !Array.isArray(children)) { 22 | return [children]; 23 | } 24 | return children; 25 | }; 26 | 27 | const resolveChildProps = child => window.dash_component_api.getLayout(child.props.componentPath)?.props; 28 | 29 | const useLoading = () => window.dash_component_api.useDashContext().useLoading() || undefined; 30 | 31 | const loadingSelector = (componentPath) => state => { 32 | 33 | let stringPath = JSON.stringify(componentPath); 34 | stringPath = stringPath.substring(0, stringPath.length - 1); 35 | 36 | const loadingChildren = toPairs(state.loading).reduce( 37 | (acc, [path, load]) => { 38 | if (path.startsWith(stringPath) && load.length) { 39 | return [...acc, load]; 40 | } 41 | return acc; 42 | }, 43 | [] 44 | ) 45 | 46 | if (loadingChildren?.length) { 47 | return flatten(loadingChildren); 48 | } 49 | return []; 50 | }; 51 | 52 | export { flatToTree, parseChildrenToArray, resolveChildProps, useLoading, loadingSelector }; -------------------------------------------------------------------------------- /src/lib/contexts/FormContext.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const FormContext = React.createContext() 4 | 5 | export default FormContext; -------------------------------------------------------------------------------- /src/lib/contexts/FormItemContext.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const FormItemContext = React.createContext() 4 | 5 | export default FormItemContext; -------------------------------------------------------------------------------- /src/lib/contexts/PropsContext.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const PropsContext = React.createContext() 4 | 5 | export default PropsContext; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdAvatarGroup.react.js: -------------------------------------------------------------------------------- 1 | // react核心W 2 | import React from 'react'; 3 | // antd核心 4 | import { Avatar } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdAvatarGroup.react'; 13 | 14 | /** 15 | * 头像组合组件AntdAvatarGroup 16 | */ 17 | const AntdAvatarGroup = (props) => { 18 | let { 19 | id, 20 | children, 21 | className, 22 | style, 23 | key, 24 | max, 25 | size, 26 | setProps, 27 | ...others 28 | } = props; 29 | 30 | return ( 31 | k.startsWith('data-') || k.startsWith('aria-'), others)} 34 | id={id} 35 | className={ 36 | isString(className) ? 37 | className : 38 | (className ? useCss(className) : undefined) 39 | } 40 | style={style} 41 | key={key} 42 | max={max} 43 | size={size} 44 | data-dash-is-loading={useLoading()} 45 | >{children} 46 | ); 47 | } 48 | 49 | export default AntdAvatarGroup; 50 | 51 | AntdAvatarGroup.defaultProps = defaultProps; 52 | AntdAvatarGroup.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdBadge.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Badge } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdBadge.react'; 13 | 14 | /** 15 | * 徽标组件AntdBadge 16 | */ 17 | const AntdBadge = (props) => { 18 | let { 19 | id, 20 | children, 21 | className, 22 | style, 23 | styles, 24 | classNames, 25 | key, 26 | color, 27 | count, 28 | dot, 29 | offset, 30 | overflowCount, 31 | showZero, 32 | status, 33 | text, 34 | title, 35 | size, 36 | nClicks, 37 | setProps, 38 | ...others 39 | } = props; 40 | 41 | return ( 42 | k.startsWith('data-') || k.startsWith('aria-'), others)} 45 | id={id} 46 | className={ 47 | isString(className) ? 48 | className : 49 | (className ? useCss(className) : undefined) 50 | } 51 | style={style} 52 | styles={styles} 53 | classNames={classNames} 54 | key={key} 55 | color={color} 56 | count={count} 57 | dot={dot} 58 | offset={(offset && offset.length === 2) ? offset : undefined} 59 | overflowCount={overflowCount} 60 | showZero={showZero} 61 | status={status} 62 | text={text} 63 | title={title} 64 | size={size} 65 | onClick={() => setProps({ nClicks: nClicks + 1 })} 66 | data-dash-is-loading={useLoading()} 67 | >{children} 68 | ); 69 | } 70 | 71 | export default AntdBadge; 72 | 73 | AntdBadge.defaultProps = defaultProps; 74 | AntdBadge.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdCarousel.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Carousel } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdCarousel.react'; 13 | 14 | /** 15 | * 走马灯组件AntdCarousel 16 | */ 17 | const AntdCarousel = (props) => { 18 | let { 19 | id, 20 | children, 21 | className, 22 | style, 23 | key, 24 | arrows, 25 | autoplay, 26 | dotPosition, 27 | easing, 28 | effect, 29 | autoplaySpeed, 30 | speed, 31 | pauseOnHover, 32 | infinite, 33 | lazyLoad, 34 | slidesToShow, 35 | slidesToScroll, 36 | setProps, 37 | ...others 38 | } = props; 39 | 40 | return ( 41 | k.startsWith('data-') || k.startsWith('aria-'), others)} 44 | id={id} 45 | className={ 46 | isString(className) ? 47 | className : 48 | (className ? useCss(className) : undefined) 49 | } 50 | style={style} 51 | key={key} 52 | arrows={arrows} 53 | autoplay={autoplay} 54 | dotPosition={dotPosition} 55 | easing={easing} 56 | effect={effect} 57 | autoplaySpeed={autoplaySpeed} 58 | speed={speed} 59 | pauseOnHover={pauseOnHover} 60 | infinite={infinite} 61 | lazyLoad={lazyLoad} 62 | slidesToShow={slidesToShow} 63 | slidesToScroll={slidesToScroll} 64 | data-dash-is-loading={useLoading()} 65 | >{(Array.isArray(children) ? children : [children]).map((child, i) =>
{child}
)}
66 | ); 67 | } 68 | 69 | export default AntdCarousel; 70 | 71 | AntdCarousel.defaultProps = defaultProps; 72 | AntdCarousel.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdCheckableTag.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Tag } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdCheckableTag.react'; 13 | 14 | const { CheckableTag } = Tag; 15 | 16 | /** 17 | * 可选择标签AntdCheckableTag 18 | */ 19 | const AntdCheckableTag = (props) => { 20 | let { 21 | id, 22 | className, 23 | style, 24 | key, 25 | content, 26 | checkedContent, 27 | unCheckedContent, 28 | checked, 29 | setProps, 30 | ...others 31 | } = props; 32 | 33 | return ( 34 | k.startsWith('data-') || k.startsWith('aria-'), others)} 37 | id={id} 38 | key={key} 39 | className={ 40 | isString(className) ? 41 | className : 42 | (className ? useCss(className) : undefined) 43 | } 44 | style={style} 45 | checked={checked} 46 | onChange={(e) => setProps({ checked: e })} 47 | data-dash-is-loading={useLoading()}> 48 | { 49 | checked ? checkedContent || content : unCheckedContent || content 50 | } 51 | 52 | ); 53 | } 54 | 55 | export default AntdCheckableTag; 56 | 57 | AntdCheckableTag.defaultProps = defaultProps; 58 | AntdCheckableTag.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdCountdown.react.js: -------------------------------------------------------------------------------- 1 | // antd核心 2 | import { Statistic, Space, Tooltip } from 'antd'; 3 | import { QuestionCircleOutlined } from "@ant-design/icons"; 4 | // 辅助库 5 | import dayjs from 'dayjs'; 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdCountdown.react'; 13 | 14 | const { Timer } = Statistic; 15 | 16 | /** 17 | * 倒计时组件AntdCountdown 18 | */ 19 | const AntdCountdown = (props) => { 20 | let { 21 | id, 22 | className, 23 | style, 24 | key, 25 | value, 26 | valueFormat, 27 | format, 28 | prefix, 29 | suffix, 30 | title, 31 | titleTooltip, 32 | valueStyle, 33 | setProps, 34 | ...others 35 | } = props; 36 | 37 | return ( 38 | k.startsWith('data-') || k.startsWith('aria-'), others)} 41 | id={id} 42 | className={ 43 | isString(className) ? 44 | className : 45 | (className ? useCss(className) : undefined) 46 | } 47 | style={style} 48 | key={key} 49 | type={'countdown'} // 指定类型为倒计时 50 | value={dayjs(value, valueFormat)} 51 | format={format} 52 | prefix={prefix} 53 | suffix={suffix} 54 | title={titleTooltip ? 55 | 56 | {title} 57 | 58 | 59 | 60 | 61 | : title} 62 | valueStyle={valueStyle} 63 | onFinish={() => setProps({ finishEvent: { timestamp: Date.now() } })} 64 | data-dash-is-loading={useLoading()} 65 | /> 66 | ); 67 | } 68 | 69 | export default AntdCountdown; 70 | 71 | AntdCountdown.defaultProps = defaultProps; 72 | AntdCountdown.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdCountup.react.js: -------------------------------------------------------------------------------- 1 | // antd核心 2 | import { Statistic, Space, Tooltip } from 'antd'; 3 | import { QuestionCircleOutlined } from "@ant-design/icons"; 4 | // 辅助库 5 | import dayjs from 'dayjs'; 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdCountup.react'; 13 | 14 | const { Timer } = Statistic; 15 | 16 | /** 17 | *正计时组件AntdCountup 18 | */ 19 | const AntdCountup = (props) => { 20 | let { 21 | id, 22 | className, 23 | style, 24 | key, 25 | value, 26 | valueFormat, 27 | format, 28 | prefix, 29 | suffix, 30 | title, 31 | titleTooltip, 32 | valueStyle, 33 | setProps, 34 | ...others 35 | } = props; 36 | 37 | return ( 38 | k.startsWith('data-') || k.startsWith('aria-'), others)} 41 | id={id} 42 | className={ 43 | isString(className) ? 44 | className : 45 | (className ? useCss(className) : undefined) 46 | } 47 | style={style} 48 | key={key} 49 | type={'countup'} // 指定类型为正计时 50 | value={dayjs(value, valueFormat)} 51 | format={format} 52 | prefix={prefix} 53 | suffix={suffix} 54 | title={titleTooltip ? 55 | 56 | {title} 57 | 58 | 59 | 60 | 61 | : title} 62 | valueStyle={valueStyle} 63 | onFinish={() => setProps({ finishEvent: { timestamp: Date.now() } })} 64 | data-dash-is-loading={useLoading()} 65 | /> 66 | ); 67 | } 68 | 69 | export default AntdCountup; 70 | 71 | AntdCountup.defaultProps = defaultProps; 72 | AntdCountup.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdEmpty.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React, { useContext } from 'react'; 3 | // antd核心 4 | import { Empty, ConfigProvider } from 'antd'; 5 | // 辅助库 6 | import { str2Locale } from '../../components/locales.react'; 7 | import { isString } from 'lodash'; 8 | import { pickBy } from 'ramda'; 9 | import { useLoading } from '../../components/utils'; 10 | // 自定义hooks 11 | import useCss from '../../hooks/useCss'; 12 | // 上下文 13 | import PropsContext from '../../contexts/PropsContext'; 14 | // 参数类型 15 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdEmpty.react'; 16 | 17 | 18 | const builtinImage = new Map([ 19 | ['default', Empty.PRESENTED_IMAGE_DEFAULT], 20 | ['simple', Empty.PRESENTED_IMAGE_SIMPLE] 21 | ]) 22 | 23 | /** 24 | * 空状态组件AntdEmpty 25 | */ 26 | const AntdEmpty = (props) => { 27 | let { 28 | id, 29 | children, 30 | className, 31 | style, 32 | styles, 33 | classNames, 34 | key, 35 | locale, 36 | description, 37 | image, 38 | setProps, 39 | ...others 40 | } = props; 41 | 42 | const context = useContext(PropsContext) 43 | locale = (context && context.locale) || locale 44 | 45 | return ( 46 | 47 | k.startsWith('data-') || k.startsWith('aria-'), others)} 50 | id={id} 51 | className={ 52 | isString(className) ? 53 | className : 54 | (className ? useCss(className) : undefined) 55 | } 56 | style={style} 57 | styles={styles} 58 | classNames={classNames} 59 | key={key} 60 | description={description} 61 | image={builtinImage.get(image) || image} 62 | data-dash-is-loading={useLoading()} > 63 | {children} 64 | 65 | 66 | ); 67 | } 68 | 69 | export default AntdEmpty; 70 | 71 | AntdEmpty.defaultProps = defaultProps; 72 | AntdEmpty.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdRibbon.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Badge } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdRibbon.react'; 13 | 14 | /** 15 | * 缎带组件AntdRibbon 16 | */ 17 | const AntdRibbon = (props) => { 18 | let { 19 | id, 20 | children, 21 | className, 22 | style, 23 | key, 24 | color, 25 | placement, 26 | text, 27 | setProps, 28 | ...others 29 | } = props; 30 | 31 | return ( 32 | k.startsWith('data-') || k.startsWith('aria-'), others)} 35 | id={id} 36 | className={ 37 | isString(className) ? 38 | className : 39 | (className ? useCss(className) : undefined) 40 | } 41 | style={style} 42 | key={key} 43 | color={color} 44 | placement={placement} 45 | text={text} 46 | data-dash-is-loading={useLoading()} 47 | >{children} 48 | ); 49 | } 50 | 51 | export default AntdRibbon; 52 | 53 | AntdRibbon.defaultProps = defaultProps; 54 | AntdRibbon.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdTag.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Tag } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdTag.react'; 13 | 14 | /** 15 | * 标签组件AntdTag 16 | */ 17 | const AntdTag = (props) => { 18 | let { 19 | id, 20 | className, 21 | style, 22 | key, 23 | content, 24 | icon, 25 | color, 26 | href, 27 | target, 28 | bordered, 29 | closeIcon, 30 | closeCounts, 31 | setProps, 32 | ...others 33 | } = props; 34 | 35 | return ( 36 | k.startsWith('data-') || k.startsWith('aria-'), others)} 39 | id={id} 40 | key={key} 41 | className={ 42 | isString(className) ? 43 | className : 44 | (className ? useCss(className) : undefined) 45 | } 46 | style={style} 47 | icon={icon} 48 | color={color} 49 | bordered={bordered} 50 | closeIcon={closeIcon} 51 | onClose={(e) => { 52 | // 阻止默认关闭事件 53 | e.preventDefault(); 54 | setProps({ 55 | closeCounts: closeCounts + 1 56 | }) 57 | }} 58 | data-dash-is-loading={useLoading()}> 59 | {href ? {content} : content} 60 | 61 | ); 62 | } 63 | 64 | export default AntdTag; 65 | 66 | AntdTag.defaultProps = defaultProps; 67 | AntdTag.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/AntdTimeline.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Timeline } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../components/dataDisplay/AntdTimeline.react'; 13 | 14 | /** 15 | * 时间轴组件AntdTimeline 16 | */ 17 | const AntdTimeline = (props) => { 18 | let { 19 | id, 20 | className, 21 | style, 22 | key, 23 | items, 24 | mode, 25 | pending, 26 | pendingDot, 27 | reverse, 28 | setProps, 29 | ...others 30 | } = props; 31 | 32 | return ( 33 | k.startsWith('data-') || k.startsWith('aria-'), others)} 36 | id={id} 37 | className={ 38 | isString(className) ? 39 | className : 40 | (className ? useCss(className) : undefined) 41 | } 42 | style={style} 43 | key={key} 44 | mode={mode} 45 | pending={pending} 46 | pendingDot={pendingDot} 47 | reverse={reverse} 48 | items={items.map( 49 | item => ( 50 | { 51 | color: item.color, 52 | dot: item.icon, 53 | label: item.label, 54 | children: item.content, 55 | position: item.position 56 | } 57 | ) 58 | )} 59 | data-dash-is-loading={useLoading()} 60 | > 61 | 62 | ); 63 | } 64 | 65 | export default AntdTimeline; 66 | 67 | AntdTimeline.defaultProps = defaultProps; 68 | AntdTimeline.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/card/AntdCardGrid.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Card } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { parseChildrenToArray, useLoading } from '../../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../../components/dataDisplay/card/AntdCardGrid.react'; 13 | 14 | /** 15 | * 卡片网格组件AntdCardGrid 16 | */ 17 | const AntdCardGrid = (props) => { 18 | let { 19 | id, 20 | children, 21 | className, 22 | style, 23 | key, 24 | hoverable, 25 | nClicks, 26 | setProps, 27 | ...others 28 | } = props; 29 | 30 | children = parseChildrenToArray(children) 31 | 32 | return ( 33 | k.startsWith('data-') || k.startsWith('aria-'), others)} 36 | id={id} 37 | className={ 38 | isString(className) ? 39 | className : 40 | (className ? useCss(className) : undefined) 41 | } 42 | style={style} 43 | key={key} 44 | hoverable={hoverable} 45 | onClick={(e) => setProps({ nClicks: nClicks + 1 })} 46 | data-dash-is-loading={useLoading()}> 47 | {children} 48 | 49 | ); 50 | } 51 | 52 | export default AntdCardGrid; 53 | 54 | AntdCardGrid.defaultProps = defaultProps; 55 | AntdCardGrid.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/card/AntdCardMeta.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // antd核心 4 | import { Card } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../../hooks/useCss'; 11 | // 参数类型 12 | import { propTypes, defaultProps } from '../../../components/dataDisplay/card/AntdCardMeta.react'; 13 | 14 | const { Meta } = Card; 15 | 16 | /** 17 | * 结构化卡片组件AntdCardMeta 18 | */ 19 | const AntdCardMeta = (props) => { 20 | let { 21 | id, 22 | className, 23 | style, 24 | key, 25 | avatar, 26 | description, 27 | title, 28 | setProps, 29 | ...others 30 | } = props; 31 | 32 | return ( 33 | k.startsWith('data-') || k.startsWith('aria-'), others)} 36 | id={id} 37 | className={ 38 | isString(className) ? 39 | className : 40 | (className ? useCss(className) : undefined) 41 | } 42 | style={style} 43 | key={key} 44 | avatar={avatar} 45 | description={description} 46 | title={title} 47 | data-dash-is-loading={useLoading()}> 48 | 49 | ); 50 | } 51 | 52 | export default AntdCardMeta; 53 | 54 | AntdCardMeta.defaultProps = defaultProps; 55 | AntdCardMeta.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataDisplay/descriptions/AntdDescriptionItem.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React from 'react'; 3 | // 辅助库 4 | import { isString } from 'lodash'; 5 | import { pickBy } from 'ramda'; 6 | import { parseChildrenToArray, useLoading } from '../../../components/utils'; 7 | // 自定义hooks 8 | import useCss from '../../../hooks/useCss'; 9 | // 参数类型 10 | import { propTypes, defaultProps } from '../../../components/dataDisplay/descriptions/AntdDescriptionItem.react'; 11 | 12 | /** 13 | * 描述列表子项组件AntdDescriptionItem 14 | */ 15 | const AntdDescriptionItem = (props) => { 16 | let { 17 | id, 18 | children, 19 | className, 20 | style, 21 | styles, 22 | classNames, 23 | key, 24 | label, 25 | span, 26 | setProps, 27 | ...others 28 | } = props; 29 | 30 | children = parseChildrenToArray(children) 31 | 32 | return ( 33 |
k.startsWith('data-') || k.startsWith('aria-'), others)} 36 | id={id} 37 | className={ 38 | isString(className) ? 39 | className : 40 | (className ? useCss(className) : undefined) 41 | } 42 | style={style} 43 | styles={styles} 44 | classNames={classNames} 45 | key={key} 46 | label={label} 47 | span={span} 48 | data-dash-is-loading={useLoading()}> 49 | {children} 50 |
51 | ); 52 | } 53 | 54 | export default AntdDescriptionItem; 55 | 56 | AntdDescriptionItem.defaultProps = defaultProps; 57 | AntdDescriptionItem.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/fragments/dataEntry/form/AntdFormItem.react.js: -------------------------------------------------------------------------------- 1 | // react核心 2 | import React, { useContext } from 'react'; 3 | // antd核心 4 | import { Form } from 'antd'; 5 | // 辅助库 6 | import { isString } from 'lodash'; 7 | import { pickBy } from 'ramda'; 8 | import { useLoading } from '../../../components/utils'; 9 | // 自定义hooks 10 | import useCss from '../../../hooks/useCss'; 11 | // 上下文 12 | import FormContext from '../../../contexts/FormContext'; 13 | // 状态管理 14 | import useFormStore from '../../../store/formStore'; 15 | // 参数类型 16 | import { propTypes, defaultProps } from '../../../components/dataEntry/form/AntdFormItem.react'; 17 | 18 | const { Item } = Form; 19 | 20 | /** 21 | * 表单项组件AntdFormItem 22 | */ 23 | const AntdFormItem = (props) => { 24 | let { 25 | id, 26 | children, 27 | className, 28 | style, 29 | key, 30 | labelCol, 31 | colon, 32 | wrapperCol, 33 | label, 34 | labelAlign, 35 | tooltip, 36 | extra, 37 | help, 38 | hidden, 39 | required, 40 | validateStatus, 41 | hasFeedback, 42 | layout, 43 | setProps, 44 | ...others 45 | } = props; 46 | 47 | const formId = useContext(FormContext); 48 | const _validateStatus = useFormStore((state) => state.validateStatuses?.[formId]?.[label]); 49 | const _help = useFormStore((state) => state.helps?.[formId]?.[label]); 50 | 51 | return ( 52 | k.startsWith('data-') || k.startsWith('aria-'), others)} 55 | id={id} 56 | className={ 57 | isString(className) ? 58 | className : 59 | (className ? useCss(className) : undefined) 60 | } 61 | style={style} 62 | key={key} 63 | labelCol={labelCol} 64 | colon={colon} 65 | wrapperCol={wrapperCol} 66 | label={label} 67 | labelAlign={labelAlign} 68 | tooltip={tooltip} 69 | extra={extra} 70 | help={help || (formId && _help)} 71 | hasFeedback={hasFeedback} 72 | hidden={hidden} 73 | required={required} 74 | validateStatus={validateStatus || (formId && _validateStatus)} 75 | layout={layout} 76 | data-dash-is-loading={useLoading()}> 77 | {children} 78 | 79 | ); 80 | } 81 | 82 | export default React.memo(AntdFormItem); 83 | 84 | AntdFormItem.defaultProps = defaultProps; 85 | AntdFormItem.propTypes = propTypes; -------------------------------------------------------------------------------- /src/lib/hooks/useCss.js: -------------------------------------------------------------------------------- 1 | import { create } from 'nano-css'; 2 | import { addon as addonCSSOM } from 'nano-css/addon/cssom'; 3 | import { addon as addonVCSSOM } from 'nano-css/addon/vcssom'; 4 | import { cssToTree } from 'nano-css/addon/vcssom/cssToTree'; 5 | import { useMemo, useEffect } from 'react'; 6 | import { v4 as uuidv4 } from 'uuid'; 7 | 8 | const nano = create(); 9 | addonCSSOM(nano); 10 | addonVCSSOM(nano); 11 | 12 | /** 13 | * 用于支持各组件的动态css类特性 14 | */ 15 | const useCss = (css) => { 16 | const className = useMemo(() => 'react-use-css-' + uuidv4(), []); 17 | const sheet = useMemo(() => new nano.VSheet(), []); 18 | useEffect(() => { 19 | const tree = {}; 20 | cssToTree(tree, css, '.' + className, ''); 21 | sheet.diff(tree); 22 | return () => { 23 | sheet.diff({}); 24 | }; 25 | }); 26 | return className; 27 | }; 28 | 29 | export default useCss; -------------------------------------------------------------------------------- /src/lib/store/formStore.js: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand'; 2 | import { omit } from 'ramda'; 3 | 4 | const useFormStore = create((set) => ({ 5 | values: {}, 6 | validateStatuses: {}, 7 | helps: {}, 8 | updateItemValue: (formId, newValueName, newValue) => set((state) => ({ 9 | values: { 10 | ...state.values, 11 | [formId]: { 12 | ...state.values[formId], 13 | [newValueName]: newValue 14 | } 15 | } 16 | })), 17 | updateFormValues: (formId, newValues) => set((state) => ({ 18 | values: { 19 | ...state.values, 20 | [formId]: newValues 21 | } 22 | })), 23 | deleteFormValues: (formId) => set((state) => ({ 24 | // 清除对应表单值 25 | values: omit([formId], state.values) 26 | })), 27 | deleteItemValue: (formId, newValueName) => set((state) => ({ 28 | values: { 29 | ...state.values, 30 | // 清除对应表单项的值 31 | [formId]: omit([newValueName], state.values[formId]) 32 | } 33 | })), 34 | updateValidateStatuses: (formId, newStatues) => set((state) => ({ 35 | validateStatuses: { 36 | ...state.validateStatuses, 37 | [formId]: newStatues 38 | } 39 | })), 40 | updateHelps: (formId, newHelps) => set((state) => ({ 41 | helps: { 42 | ...state.helps, 43 | [formId]: newHelps 44 | } 45 | })) 46 | })); 47 | 48 | export default useFormStore; -------------------------------------------------------------------------------- /tests/dash3.0tests/AntdQRCode组件loading状态重构/test.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import time 6 | import dash 7 | from dash import html 8 | import feffery_antd_components as fac 9 | from dash.dependencies import Input, Output, State 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdQRCode( 17 | id='auto-spin-qrcode-demo', 18 | value='https://fac.feffery.tech/', 19 | autoSpin=True, 20 | ), 21 | fac.AntdButton( 22 | '重新生成', 23 | id='auto-spin-qrcode-demo-button', 24 | type='primary', 25 | ), 26 | ], 27 | direction='vertical', 28 | align='center', 29 | ) 30 | ) 31 | 32 | 33 | @app.callback( 34 | Output('auto-spin-qrcode-demo', 'value'), 35 | Input('auto-spin-qrcode-demo-button', 'nClicks'), 36 | State('auto-spin-qrcode-demo', 'value'), 37 | prevent_initial_call=True, 38 | ) 39 | def auto_spin_qrcode_demo_input_callback(nClicks, value): 40 | if nClicks: 41 | time.sleep(1) 42 | if value == 'https://fac.feffery.tech/': 43 | return 'https://ant.design/' 44 | elif value == 'https://ant.design/': 45 | return 'https://fac.feffery.tech/' 46 | 47 | return dash.no_update 48 | 49 | 50 | if __name__ == '__main__': 51 | app.run(debug=True) 52 | -------------------------------------------------------------------------------- /tests/dash3.0tests/AntdTable函数式改造/test.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | from datetime import datetime 8 | import feffery_antd_components as fac 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | [ 15 | fac.AntdTable( 16 | columns=[ 17 | { 18 | 'title': 'int型示例', 19 | 'dataIndex': 'int型示例', 20 | }, 21 | { 22 | 'title': 'float型示例', 23 | 'dataIndex': 'float型示例', 24 | }, 25 | { 26 | 'title': 'str型示例', 27 | 'dataIndex': 'str型示例', 28 | }, 29 | { 30 | 'title': '日期时间示例', 31 | 'dataIndex': '日期时间示例', 32 | }, 33 | ], 34 | data=[ 35 | { 36 | 'int型示例': 123, 37 | 'float型示例': 1.23, 38 | 'str型示例': '示例字符', 39 | '日期时间示例': datetime.now(), 40 | } 41 | ] 42 | * 20, 43 | ), 44 | fac.AntdTable( 45 | columns=[ 46 | { 47 | 'title': '搜索型筛选', 48 | 'dataIndex': '搜索型筛选', 49 | } 50 | ], 51 | data=[{'搜索型筛选': s} for s in list('abced')], 52 | filterOptions={ 53 | '搜索型筛选': {'filterMode': 'keyword'} 54 | }, 55 | style={'width': 200}, 56 | ), 57 | ], 58 | style=style(padding=50), 59 | ) 60 | 61 | if __name__ == '__main__': 62 | app.run(debug=True) 63 | -------------------------------------------------------------------------------- /tests/dash3.0tests/_dashprivate_layout改动测试/test.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | html.Div(fac.__version__), 15 | fac.AntdDescriptions( 16 | [ 17 | fac.AntdDescriptionItem( 18 | '费弗里', label='姓名' 19 | ), 20 | fac.AntdDescriptionItem( 21 | html.A( 22 | 'https://github.com/CNFeffery', 23 | href='https://github.com/CNFeffery', 24 | ), 25 | label='个人Github地址', 26 | ), 27 | fac.AntdDescriptionItem( 28 | html.A( 29 | 'https://www.cnblogs.com/feffery/', 30 | href='https://www.cnblogs.com/feffery/', 31 | ), 32 | label='个人博客地址', 33 | ), 34 | fac.AntdDescriptionItem( 35 | html.A( 36 | 'http://fac.feffery.tech/', 37 | href='http://fac.feffery.tech/', 38 | ), 39 | label='fac框架官网', 40 | ), 41 | ], 42 | title='描述列表示例', 43 | labelStyle={'fontWeight': 'bold'}, 44 | ), 45 | ], 46 | style=style(padding=50), 47 | ) 48 | 49 | if __name__ == '__main__': 50 | app.run(debug=True) 51 | -------------------------------------------------------------------------------- /tests/dash3.0tests/loading_state改动测试/test.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import time 6 | import dash 7 | from dash import html 8 | import feffery_antd_components as fac 9 | from dash.dependencies import Input, Output 10 | from feffery_dash_utils.style_utils import style 11 | 12 | app = dash.Dash(__name__) 13 | 14 | app.layout = html.Div( 15 | [ 16 | fac.AntdButton( 17 | '测试', 18 | id='button-demo', 19 | type='primary', 20 | ) 21 | ], 22 | style=style(padding=50), 23 | ) 24 | 25 | 26 | @app.callback( 27 | Output('button-demo', 'children'), 28 | Input('button-demo', 'nClicks'), 29 | prevent_initial_call=True, 30 | ) 31 | def demo_callback(nClicks): 32 | time.sleep(3) 33 | 34 | return f'nClicks: {nClicks}' 35 | 36 | 37 | if __name__ == '__main__': 38 | app.run(debug=True) 39 | -------------------------------------------------------------------------------- /tests/dash3.0tests/函数式组件默认值重构/test.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdButton( 15 | '测试', 16 | id='button-demo', 17 | type='primary', 18 | **{'data-test': 'test'}, 19 | ), 20 | fac.AntdTag( 21 | content='测试', 22 | href='/test', 23 | **{'data-test': 'test'}, 24 | ), 25 | ], 26 | style=style(padding=50), 27 | ) 28 | 29 | if __name__ == '__main__': 30 | app.run(debug=True) 31 | -------------------------------------------------------------------------------- /tests/dash3.0tests/加载动画类组件重构测试/test.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import time 6 | import dash 7 | from dash import html 8 | import feffery_antd_components as fac 9 | from dash.dependencies import Input, Output 10 | from feffery_dash_utils.style_utils import style 11 | 12 | app = dash.Dash(__name__) 13 | 14 | app.layout = html.Div( 15 | html.Div( 16 | [ 17 | '测试', 18 | fac.AntdCustomSkeleton( 19 | [ 20 | html.Div( 21 | html.Div( 22 | fac.AntdButton( 23 | '测试', 24 | id='button-demo', 25 | type='primary', 26 | ) 27 | ) 28 | ), 29 | html.Div(id='inner-output-test'), 30 | ], 31 | skeletonContent='加载中...', 32 | ), 33 | html.Div(id='outer-output-test'), 34 | ], 35 | style=style(padding=50), 36 | ) 37 | ) 38 | 39 | 40 | @app.callback( 41 | [ 42 | Output('button-demo', 'children'), 43 | Output('button-demo', 'type'), 44 | Output('inner-output-test', 'children'), 45 | Output('outer-output-test', 'children'), 46 | ], 47 | Input('button-demo', 'nClicks'), 48 | prevent_initial_call=True, 49 | ) 50 | def demo_callback(nClicks): 51 | time.sleep(3) 52 | 53 | return [ 54 | f'nClicks: {nClicks}', 55 | dash.no_update, 56 | f'inner: {nClicks}', 57 | f'outer: {nClicks}', 58 | ] 59 | 60 | 61 | if __name__ == '__main__': 62 | app.run(debug=True) 63 | -------------------------------------------------------------------------------- /tests/dash3.0tests/组件属性基础持久化重构测试/test.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdCollapse( 15 | '测试内容', 16 | id='persistence-test', 17 | title='测试', 18 | persistence=True, 19 | ) 20 | ], 21 | style=style(padding=50), 22 | ) 23 | 24 | if __name__ == '__main__': 25 | app.run(debug=True) 26 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdAccordion/feat_size.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdSpace( 13 | [ 14 | fac.AntdAccordion( 15 | items=[ 16 | { 17 | 'title': f'手风琴项示例{i}', 18 | 'key': i, 19 | 'children': fac.AntdText( 20 | f'手风琴项示例{i}' 21 | ), 22 | } 23 | for i in range(1, 6) 24 | ], 25 | size=size, 26 | ) 27 | for size in ['small', 'middle', 'large'] 28 | ], 29 | direction='vertical', 30 | style=style(width='100%'), 31 | ), 32 | style=style(padding=50), 33 | ) 34 | 35 | if __name__ == '__main__': 36 | app.run(debug=True) 37 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdAccordion/feat_styles.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdAccordion( 13 | items=[ 14 | { 15 | 'title': f'手风琴项示例{i}', 16 | 'key': i, 17 | 'children': fac.AntdText( 18 | f'手风琴项示例{i}' 19 | ), 20 | } 21 | for i in range(1, 6) 22 | ], 23 | styles={ 24 | 'header': { 25 | 'background': '#40a9ff', 26 | 'color': '#fff', 27 | }, 28 | 'body': {'background': '#597ef7'}, 29 | }, 30 | ), 31 | style=style(padding=50), 32 | ) 33 | 34 | if __name__ == '__main__': 35 | app.run(debug=True) 36 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdCarousel/feat_auto_play_dot_duration.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdCarousel( 15 | [ 16 | fac.AntdCenter( 17 | i, 18 | style={ 19 | 'color': 'white', 20 | 'fontSize': 36, 21 | 'height': 160, 22 | 'backgroundColor': '#364d79', 23 | }, 24 | ) 25 | for i in range(1, 6) 26 | ], 27 | autoplay={'dotDuration': True}, 28 | ) 29 | ], 30 | style=style(padding=50), 31 | ) 32 | 33 | if __name__ == '__main__': 34 | app.run(debug=True) 35 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdCollapse/feat_size.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdSpace( 13 | [ 14 | fac.AntdCollapse( 15 | fac.AntdParagraph('内容示例' * 20), 16 | isOpen=False, 17 | title='折叠面板示例', 18 | size=size, 19 | style={'width': 300}, 20 | ) 21 | for size in ['small', 'middle', 'large'] 22 | ], 23 | direction='vertical', 24 | style=style(width='100%'), 25 | ), 26 | style=style(padding=50), 27 | ) 28 | 29 | if __name__ == '__main__': 30 | app.run(debug=True) 31 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdCollapse/feat_styles.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdCollapse( 13 | fac.AntdParagraph('内容示例' * 20), 14 | isOpen=False, 15 | title='折叠面板示例', 16 | style={'width': 300}, 17 | styles={ 18 | 'header': { 19 | 'background': '#40a9ff', 20 | 'color': '#fff', 21 | }, 22 | 'body': {'background': '#597ef7'}, 23 | }, 24 | ), 25 | style=style(padding=50), 26 | ) 27 | 28 | if __name__ == '__main__': 29 | app.run(debug=True) 30 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdCountdown/feat_finish_event.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from datetime import datetime, timedelta 8 | from dash.dependencies import Input, Output 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = lambda: fac.AntdCenter( 14 | [ 15 | fac.AntdCountdown( 16 | id='countdown-demo', 17 | value=( 18 | datetime.now() + timedelta(seconds=6) 19 | ).strftime('%Y-%m-%d %H:%M:%S:%f'), 20 | format='HH:mm:ss:SSS', 21 | ), 22 | fac.Fragment(id='message'), 23 | ], 24 | style=style(padding=50), 25 | ) 26 | 27 | 28 | @app.callback( 29 | Output('message', 'children'), 30 | Input('countdown-demo', 'finishEvent'), 31 | prevent_initial_call=True, 32 | ) 33 | def show_finish_event(finishEvent): 34 | return fac.AntdNotification( 35 | message='倒计时结束:' 36 | + str(finishEvent['timestamp']), 37 | ) 38 | 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdCountdown/refactor_to_timer.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from datetime import datetime, timedelta 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | deadline = datetime.now() + timedelta( 13 | seconds=2 * 24 * 60 * 60 + 30 14 | ) 15 | 16 | app.layout = lambda: fac.AntdCenter( 17 | [ 18 | fac.AntdRow( 19 | [ 20 | fac.AntdCol( 21 | fac.AntdCountdown( 22 | title='Countdown', 23 | value=deadline.strftime( 24 | '%Y-%m-%d %H:%M:%S:%f' 25 | ), 26 | ), 27 | span=12, 28 | ), 29 | fac.AntdCol( 30 | fac.AntdCountdown( 31 | title='Million Seconds', 32 | value=deadline.strftime( 33 | '%Y-%m-%d %H:%M:%S:%f' 34 | ), 35 | format='HH:mm:ss:SSS', 36 | ), 37 | span=12, 38 | ), 39 | fac.AntdCol( 40 | fac.AntdCountdown( 41 | title='Day Level', 42 | value=deadline.strftime( 43 | '%Y-%m-%d %H:%M:%S:%f' 44 | ), 45 | format='D 天 H 时 m 分 s 秒', 46 | ), 47 | span=24, 48 | ), 49 | ], 50 | gutter=16, 51 | ) 52 | ], 53 | style=style(padding=50), 54 | ) 55 | 56 | if __name__ == '__main__': 57 | app.run(debug=True) 58 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdCountup/refactor_to_timer.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from datetime import datetime, timedelta 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | start_datetime = datetime.now() - timedelta( 13 | seconds=2 * 24 * 60 * 60 + 30 14 | ) 15 | 16 | app.layout = lambda: fac.AntdCenter( 17 | [ 18 | fac.AntdRow( 19 | [ 20 | fac.AntdCol( 21 | fac.AntdCountup( 22 | title='Countdown', 23 | value=start_datetime.strftime( 24 | '%Y-%m-%d %H:%M:%S:%f' 25 | ), 26 | ), 27 | span=12, 28 | ), 29 | fac.AntdCol( 30 | fac.AntdCountup( 31 | title='Million Seconds', 32 | value=start_datetime.strftime( 33 | '%Y-%m-%d %H:%M:%S:%f' 34 | ), 35 | format='HH:mm:ss:SSS', 36 | ), 37 | span=12, 38 | ), 39 | fac.AntdCol( 40 | fac.AntdCountup( 41 | title='Day Level', 42 | value=start_datetime.strftime( 43 | '%Y-%m-%d %H:%M:%S:%f' 44 | ), 45 | format='D 天 H 时 m 分 s 秒', 46 | ), 47 | span=24, 48 | ), 49 | ], 50 | gutter=16, 51 | ) 52 | ], 53 | style=style(padding=50), 54 | ) 55 | 56 | if __name__ == '__main__': 57 | app.run(debug=True) 58 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdDescriptions/feat_span_filled.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdDescriptions( 15 | items=[ 16 | { 17 | 'label': 'item1', 18 | 'children': 'default span', 19 | }, 20 | { 21 | 'label': 'item2', 22 | 'children': 'span="filled"', 23 | 'span': 'filled', 24 | }, 25 | { 26 | 'label': 'item3', 27 | 'children': 'span="filled"', 28 | 'span': 'filled', 29 | }, 30 | { 31 | 'label': 'item4', 32 | 'children': 'default span', 33 | }, 34 | ], 35 | bordered=True, 36 | ) 37 | ], 38 | style=style(padding=50), 39 | ) 40 | 41 | if __name__ == '__main__': 42 | app.run(debug=True) 43 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdImage/debug_preview_toolbar.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdImage( 15 | src='https://fac.feffery.tech/assets/imgs/components/AntdImage/%E7%A4%BA%E4%BE%8B%E5%9B%BE%E7%89%871.jpg', 16 | height=400, 17 | ) 18 | ], 19 | style=style(padding=50), 20 | ) 21 | 22 | if __name__ == '__main__': 23 | app.run(debug=True) 24 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdSegmented/feat_shape.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdSegmented( 16 | options=[ 17 | { 18 | 'value': 'sun', 19 | 'icon': 'antd-sun', 20 | }, 21 | { 22 | 'value': 'moon', 23 | 'icon': 'antd-moon', 24 | }, 25 | ], 26 | value='sun', 27 | shape='round', 28 | size=size, 29 | ) 30 | for size in ['small', 'middle', 'large'] 31 | ], 32 | direction='vertical', 33 | style={'width': '100%'}, 34 | ), 35 | style=style(padding=50), 36 | ) 37 | 38 | if __name__ == '__main__': 39 | app.run(debug=True) 40 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdSegmented/feat_simple_options.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdSpace( 13 | [ 14 | fac.AntdSegmented( 15 | options=[ 16 | 'antd-carry-out', 17 | 'antd-branches', 18 | 'antd-team', 19 | 'antd-send', 20 | 'antd-setting', 21 | ], 22 | defaultValue='antd-carry-out', 23 | ), 24 | fac.AntdSegmented( 25 | options=[ 26 | {'label': i, 'value': i} 27 | for i in [ 28 | 'Daily', 29 | 'Weekly', 30 | 'Monthly', 31 | 'Quarterly', 32 | 'Yearly', 33 | ] 34 | ], 35 | defaultValue='Daily', 36 | ), 37 | ] 38 | ), 39 | style=style(height='100vh'), 40 | ) 41 | 42 | if __name__ == '__main__': 43 | app.run(debug=True) 44 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdSegmented/feat_vertical.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdSegmented( 13 | options=[ 14 | {'value': i, 'icon': icon} 15 | for i, icon in enumerate( 16 | [ 17 | 'antd-carry-out', 18 | 'antd-branches', 19 | 'antd-team', 20 | 'antd-send', 21 | 'antd-setting', 22 | ] 23 | ) 24 | ], 25 | defaultValue=0, 26 | vertical=True, 27 | ), 28 | style=style(height='100vh'), 29 | ) 30 | 31 | if __name__ == '__main__': 32 | app.run(debug=True) 33 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_columns_fixed_bool.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | html.Div( 15 | fac.AntdTable( 16 | columns=[ 17 | { 18 | 'title': f'字段{i}', 19 | 'dataIndex': f'字段{i}', 20 | 'fixed': i <= 2, 21 | } 22 | for i in range(1, 6) 23 | ], 24 | data=[ 25 | { 26 | f'字段{i}': '示例内容' 27 | for i in range(1, 6) 28 | } 29 | ] 30 | * 3, 31 | maxWidth=900, 32 | ), 33 | style={'maxWidth': 700, 'margin': '0 auto'}, 34 | ) 35 | ], 36 | style=style(position='relative', height='100vh'), 37 | ) 38 | 39 | if __name__ == '__main__': 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_columns_min_width.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | from datetime import datetime 8 | import feffery_antd_components as fac 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | [ 15 | fac.AntdTable( 16 | columns=[ 17 | { 18 | 'title': 'int型示例', 19 | 'dataIndex': 'int型示例', 20 | 'minWidth': '500px' 21 | }, 22 | { 23 | 'title': 'float型示例', 24 | 'dataIndex': 'float型示例', 25 | }, 26 | { 27 | 'title': 'str型示例', 28 | 'dataIndex': 'str型示例', 29 | }, 30 | { 31 | 'title': '日期时间示例', 32 | 'dataIndex': '日期时间示例', 33 | }, 34 | ], 35 | data=[ 36 | { 37 | 'int型示例': 123, 38 | 'float型示例': 1.23, 39 | 'str型示例': '示例字符', 40 | '日期时间示例': datetime.now(), 41 | } 42 | ] 43 | * 3, 44 | tableLayout='auto' 45 | ) 46 | ], 47 | style=style(position='relative', height='100vh'), 48 | ) 49 | 50 | if __name__ == '__main__': 51 | app.run(debug=True) 52 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_editable_disabled_keys.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | from datetime import datetime 8 | import feffery_antd_components as fac 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTable( 15 | columns=[ 16 | { 17 | 'title': 'int型示例', 18 | 'dataIndex': 'int型示例', 19 | 'editable': True, 20 | 'width': '20%', 21 | }, 22 | { 23 | 'title': 'float型示例', 24 | 'dataIndex': 'float型示例', 25 | 'editable': True, 26 | 'width': '20%', 27 | }, 28 | { 29 | 'title': 'str型示例', 30 | 'dataIndex': 'str型示例', 31 | 'editable': True, 32 | 'width': '20%', 33 | }, 34 | { 35 | 'title': '日期时间示例', 36 | 'dataIndex': '日期时间示例', 37 | 'editable': True, 38 | 'width': '20%', 39 | }, 40 | { 41 | 'title': 'placeholder示例', 42 | 'dataIndex': 'placeholder示例', 43 | 'editable': True, 44 | 'width': '20%', 45 | 'editOptions': { 46 | 'placeholder': '请输入内容', 47 | 'disabledKeys': ['row-1', 'row-5'], 48 | }, 49 | }, 50 | ], 51 | data=[ 52 | { 53 | 'key': f'row-{i}', 54 | 'int型示例': 123, 55 | 'float型示例': 1.23, 56 | 'str型示例': '示例字符', 57 | '日期时间示例': datetime.now().strftime( 58 | '%Y-%m-%d %H:%M:%S' 59 | ), 60 | } 61 | for i in range(10) 62 | ], 63 | bordered=True, 64 | ) 65 | ], 66 | style={'padding': 100}, 67 | ) 68 | 69 | 70 | if __name__ == '__main__': 71 | app.run(debug=True) 72 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_header_align.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdTable( 14 | columns=[ 15 | { 16 | 'title': align, 17 | 'dataIndex': align, 18 | 'align': align, 19 | 'headerAlign': 'right', 20 | } 21 | for align in ['left', 'center', 'right'] 22 | ], 23 | data=[ 24 | { 25 | align: 999 26 | for align in ['left', 'center', 'right'] 27 | } 28 | ] 29 | * 3, 30 | bordered=True, 31 | ) 32 | ], 33 | style={'padding': 100}, 34 | ) 35 | 36 | 37 | if __name__ == '__main__': 38 | app.run(debug=True) 39 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_loading.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import time 7 | import random 8 | from dash import html 9 | import feffery_antd_components as fac 10 | from dash.dependencies import Input, Output 11 | from feffery_dash_utils.style_utils import style 12 | 13 | app = dash.Dash(__name__) 14 | 15 | app.layout = html.Div( 16 | [ 17 | fac.AntdSpace( 18 | [ 19 | fac.AntdButton( 20 | '刷新数据', 21 | id='update-data', 22 | type='primary', 23 | loadingChildren='刷新中', 24 | ), 25 | fac.AntdTable( 26 | id='table', 27 | columns=[ 28 | { 29 | 'dataIndex': f'字段{i}', 30 | 'title': f'字段{i}', 31 | } 32 | for i in range(10) 33 | ], 34 | data=[ 35 | { 36 | f'字段{i}': random.randint( 37 | 1, 100 38 | ) 39 | for i in range(10) 40 | } 41 | for _ in range(10) 42 | ], 43 | bordered=True, 44 | ), 45 | ], 46 | direction='vertical', 47 | style=style(width='100%'), 48 | ), 49 | ], 50 | style={'padding': 100}, 51 | ) 52 | 53 | 54 | @app.callback( 55 | Output('table', 'data'), 56 | Input('update-data', 'nClicks'), 57 | running=[ 58 | [Output('update-data', 'loading'), True, False], 59 | [Output('table', 'loading'), True, False], 60 | ], 61 | prevent_initial_call=True, 62 | ) 63 | def update_data(nClicks): 64 | time.sleep(1) 65 | 66 | return [ 67 | { 68 | f'字段{i}': random.randint(1, 100) 69 | for i in range(10) 70 | } 71 | for _ in range(10) 72 | ] 73 | 74 | 75 | if __name__ == '__main__': 76 | app.run(debug=True) 77 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_row_class_name.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import random 7 | from dash import html 8 | import feffery_antd_components as fac 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTable( 15 | id='table', 16 | columns=[ 17 | { 18 | 'dataIndex': f'字段{i}', 19 | 'title': f'字段{i}', 20 | } 21 | for i in range(10) 22 | ], 23 | data=[ 24 | { 25 | f'字段{i}': random.randint(1, 100) 26 | for i in range(10) 27 | } 28 | for _ in range(10) 29 | ], 30 | bordered=True, 31 | rowClassName='test-row-class-name', 32 | ), 33 | ], 34 | style={'padding': 100}, 35 | ) 36 | 37 | 38 | if __name__ == '__main__': 39 | app.run(debug=True) 40 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_row_class_name_func.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import random 7 | from dash import html 8 | import feffery_antd_components as fac 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTable( 15 | id='table', 16 | columns=[ 17 | { 18 | 'dataIndex': f'字段{i}', 19 | 'title': f'字段{i}', 20 | } 21 | for i in range(10) 22 | ], 23 | data=[ 24 | { 25 | f'字段{i}': random.randint(1, 100) 26 | for i in range(10) 27 | } 28 | for _ in range(10) 29 | ], 30 | bordered=True, 31 | rowClassName={ 32 | 'func': '(record, index) => `row-${index}`' 33 | }, 34 | ), 35 | ], 36 | style={'padding': 100}, 37 | ) 38 | 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/feat_table_scroll.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | from datetime import datetime 8 | import feffery_antd_components as fac 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTable( 15 | columns=[ 16 | { 17 | 'title': 'int型示例', 18 | 'dataIndex': 'int型示例', 19 | }, 20 | { 21 | 'title': 'float型示例', 22 | 'dataIndex': 'float型示例', 23 | }, 24 | { 25 | 'title': 'str型示例', 26 | 'dataIndex': 'str型示例', 27 | }, 28 | { 29 | 'title': '日期时间示例', 30 | 'dataIndex': '日期时间示例', 31 | }, 32 | ], 33 | data=[ 34 | { 35 | 'int型示例': 123, 36 | 'float型示例': 1.23, 37 | 'str型示例': '示例字符', 38 | '日期时间示例': datetime.now(), 39 | '布尔类型示例': True, 40 | } 41 | ] 42 | * 100, 43 | maxHeight=300, 44 | scrollToFirstRowOnChange=False, 45 | bordered=True, 46 | maxWidth='max-content', 47 | ) 48 | ], 49 | style={'padding': 100}, 50 | ) 51 | 52 | 53 | if __name__ == '__main__': 54 | app.run(debug=True) 55 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/fix_context_locale.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdConfigProvider( 14 | fac.AntdTable( 15 | columns=[ 16 | { 17 | 'title': '搜索型筛选', 18 | 'dataIndex': '搜索型筛选', 19 | } 20 | ], 21 | data=[ 22 | {'搜索型筛选': s} for s in list('abced') 23 | ], 24 | filterOptions={ 25 | '搜索型筛选': {'filterMode': 'keyword'} 26 | }, 27 | style={'width': 200}, 28 | ), 29 | locale='en-us', 30 | ) 31 | ], 32 | style={'padding': 50}, 33 | ) 34 | 35 | 36 | if __name__ == '__main__': 37 | app.run(debug=True) 38 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/fix_field_bool.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | from datetime import datetime 8 | import feffery_antd_components as fac 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTable( 15 | columns=[ 16 | { 17 | 'title': 'int型示例', 18 | 'dataIndex': 'int型示例', 19 | }, 20 | { 21 | 'title': 'float型示例', 22 | 'dataIndex': 'float型示例', 23 | }, 24 | { 25 | 'title': 'str型示例', 26 | 'dataIndex': 'str型示例', 27 | }, 28 | { 29 | 'title': '日期时间示例', 30 | 'dataIndex': '日期时间示例', 31 | }, 32 | ], 33 | data=[ 34 | { 35 | 'int型示例': 123, 36 | 'float型示例': 1.23, 37 | 'str型示例': '示例字符', 38 | '日期时间示例': datetime.now(), 39 | '布尔类型示例': True, 40 | } 41 | ] 42 | * 3, 43 | ) 44 | ], 45 | style={'padding': 100}, 46 | ) 47 | 48 | 49 | if __name__ == '__main__': 50 | app.run(debug=True) 51 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTable/fix_summary_multi_level_header.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdTable( 14 | columns=[ 15 | { 16 | 'title': '字段1', 17 | 'dataIndex': '字段1', 18 | }, 19 | { 20 | 'title': '字段2', 21 | 'dataIndex': '字段2', 22 | }, 23 | { 24 | 'title': '字段3', 25 | 'dataIndex': '字段3', 26 | 'group': '组1', 27 | }, 28 | { 29 | 'title': '字段4', 30 | 'dataIndex': '字段4', 31 | 'group': '组1', 32 | }, 33 | { 34 | 'title': '字段5', 35 | 'dataIndex': '字段5', 36 | }, 37 | { 38 | 'title': '字段6', 39 | 'dataIndex': '字段6', 40 | }, 41 | ], 42 | data=[ 43 | { 44 | f'字段{i}': f'示例内容{i}' 45 | for i in range(1, 7) 46 | } 47 | ] 48 | * 5, 49 | bordered=True, 50 | summaryRowContents=[ 51 | {'content': '第1列总结', 'align': 'center'}, 52 | { 53 | 'content': '第2到3列总结', 54 | 'colSpan': 2, 55 | 'align': 'center', 56 | }, 57 | {'content': '第4列总结', 'align': 'center'}, 58 | { 59 | 'content': '第5到6列总结', 60 | 'colSpan': 2, 61 | 'align': 'center', 62 | }, 63 | {'content': 'xxx', 'align': 'center'}, 64 | { 65 | 'content': 'xxx', 66 | 'colSpan': 2, 67 | 'align': 'center', 68 | }, 69 | {'content': 'xxx', 'align': 'center'}, 70 | { 71 | 'content': 'xxx', 72 | 'colSpan': 2, 73 | 'align': 'center', 74 | }, 75 | ], 76 | rowSelectionType='radio', 77 | summaryRowBlankColumns=1, 78 | ), 79 | ], 80 | style={'padding': 100}, 81 | ) 82 | 83 | 84 | if __name__ == '__main__': 85 | app.run(debug=True) 86 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTabs/feat_item_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTabs( 15 | items=[ 16 | { 17 | 'key': f'标签页{i}', 18 | 'label': f'标签页{i}', 19 | 'icon': fac.AntdIcon( 20 | icon='antd-function' 21 | ), 22 | 'children': fac.AntdCenter( 23 | f'这是标签页{i}的内容示例', 24 | style={ 25 | 'fontSize': 18, 26 | 'background': f'rgba(28, 126, 214, calc(1 - 0.2 * {i}))', 27 | 'height': 200, 28 | }, 29 | ), 30 | } 31 | for i in range(1, 6) 32 | ] 33 | ) 34 | ], 35 | style=style(padding=50), 36 | ) 37 | 38 | if __name__ == '__main__': 39 | app.run(debug=True) 40 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTabs/feat_tab_bar_style.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTabs( 15 | items=[ 16 | { 17 | 'key': f'标签页{i}', 18 | 'label': f'标签页{i}', 19 | 'icon': fac.AntdIcon( 20 | icon='antd-function' 21 | ), 22 | 'children': fac.AntdCenter( 23 | f'这是标签页{i}的内容示例', 24 | style={ 25 | 'fontSize': 18, 26 | 'background': f'rgba(28, 126, 214, calc(1 - 0.2 * {i}))', 27 | 'height': 200, 28 | }, 29 | ), 30 | } 31 | for i in range(1, 6) 32 | ], 33 | tabBarStyle=style(background='#d9d9d9'), 34 | ) 35 | ], 36 | style=style(padding=50), 37 | ) 38 | 39 | if __name__ == '__main__': 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /tests/dataDisplay/AntdTree/feat_async_data_load.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import time 6 | import dash 7 | from dash import html 8 | import feffery_antd_components as fac 9 | from feffery_dash_utils.tree_utils import TreeManager 10 | from dash.dependencies import Input, Output, State 11 | 12 | app = dash.Dash(__name__) 13 | 14 | app.layout = html.Div( 15 | [ 16 | fac.AntdTree( 17 | id='tree-demo', 18 | treeData=[ 19 | { 20 | 'key': '节点1', 21 | 'title': '节点1', 22 | }, 23 | { 24 | 'key': '节点2', 25 | 'title': '节点2', 26 | 'children': [ 27 | { 28 | 'key': '节点2-1', 29 | 'title': '节点2-1', 30 | 'isLeaf': True, 31 | }, 32 | ], 33 | }, 34 | { 35 | 'key': '节点3', 36 | 'title': '节点3', 37 | 'isLeaf': True, 38 | }, 39 | ], 40 | enableAsyncLoad=True, 41 | ) 42 | ], 43 | style={'padding': 100}, 44 | ) 45 | 46 | 47 | @app.callback( 48 | Output('tree-demo', 'treeData'), 49 | Input('tree-demo', 'loadingNode'), 50 | State('tree-demo', 'treeData'), 51 | prevent_initial_call=True, 52 | ) 53 | def tree_demo(loadingNode, treeData): 54 | time.sleep(0.5) 55 | return TreeManager.update_tree_node( 56 | treeData, 57 | node_key=loadingNode['key'], 58 | new_node={ 59 | 'children': [ 60 | { 61 | 'key': loadingNode['key'] + '-1', 62 | 'title': loadingNode['key'] + '-1', 63 | } 64 | ] 65 | }, 66 | mode='overlay', 67 | ) 68 | 69 | 70 | if __name__ == '__main__': 71 | app.run(debug=True) 72 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdCalendar/feat_custom_cells.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdCalendar( 14 | size='large', 15 | customCells=[ 16 | { 17 | 'type': 'date', 18 | 'month': 8, 19 | 'date': 1, 20 | 'content': fac.AntdTag( 21 | content='建军节', color='red' 22 | ), 23 | }, 24 | { 25 | 'type': 'date', 26 | 'date': 15, 27 | 'content': fac.AntdTag( 28 | content='月中', color='blue' 29 | ), 30 | }, 31 | { 32 | 'type': 'month', 33 | 'month': 7, 34 | 'content': fac.AntdTag( 35 | content='暑假', color='red' 36 | ), 37 | }, 38 | { 39 | 'type': 'month', 40 | 'month': 8, 41 | 'content': fac.AntdTag( 42 | content='暑假', color='red' 43 | ), 44 | }, 45 | ], 46 | ) 47 | ], 48 | style={'padding': 100}, 49 | ) 50 | 51 | if __name__ == '__main__': 52 | app.run(debug=True) 53 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdCascader/feat_prefix.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdCascader( 14 | placeholder='请选择', 15 | prefix=fac.AntdIcon(icon='antd-user'), 16 | options=[ 17 | { 18 | 'value': '节点1', 19 | 'label': '节点1', 20 | 'children': [ 21 | { 22 | 'value': '节点1-1', 23 | 'label': '节点1-1', 24 | }, 25 | { 26 | 'value': '节点1-2', 27 | 'label': '节点1-2', 28 | 'children': [ 29 | { 30 | 'value': '节点1-2-1', 31 | 'label': '节点1-2-1', 32 | }, 33 | { 34 | 'value': '节点1-2-2', 35 | 'label': '节点1-2-2', 36 | }, 37 | ], 38 | }, 39 | ], 40 | }, 41 | { 42 | 'value': '节点2', 43 | 'label': '节点2', 44 | 'children': [ 45 | { 46 | 'value': '节点2-1', 47 | 'label': '节点2-1', 48 | }, 49 | { 50 | 'value': '节点2-2', 51 | 'label': '节点2-2', 52 | }, 53 | ], 54 | }, 55 | ], 56 | ) 57 | ], 58 | style={'padding': 100}, 59 | ) 60 | 61 | if __name__ == '__main__': 62 | app.run(debug=True) 63 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdCascader/feat_suffix_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdCascader( 14 | placeholder='请选择', 15 | suffixIcon=fac.AntdIcon(icon='antd-user'), 16 | options=[ 17 | { 18 | 'value': '节点1', 19 | 'label': '节点1', 20 | 'children': [ 21 | { 22 | 'value': '节点1-1', 23 | 'label': '节点1-1', 24 | }, 25 | { 26 | 'value': '节点1-2', 27 | 'label': '节点1-2', 28 | 'children': [ 29 | { 30 | 'value': '节点1-2-1', 31 | 'label': '节点1-2-1', 32 | }, 33 | { 34 | 'value': '节点1-2-2', 35 | 'label': '节点1-2-2', 36 | }, 37 | ], 38 | }, 39 | ], 40 | }, 41 | { 42 | 'value': '节点2', 43 | 'label': '节点2', 44 | 'children': [ 45 | { 46 | 'value': '节点2-1', 47 | 'label': '节点2-1', 48 | }, 49 | { 50 | 'value': '节点2-2', 51 | 'label': '节点2-2', 52 | }, 53 | ], 54 | }, 55 | ], 56 | ) 57 | ], 58 | style={'padding': 100}, 59 | ) 60 | 61 | if __name__ == '__main__': 62 | app.run(debug=True) 63 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdCascader/fix_read_only.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdCascader( 17 | placeholder='请选择', 18 | options=[ 19 | { 20 | 'value': '节点1', 21 | 'label': '节点1', 22 | 'children': [ 23 | { 24 | 'value': '节点1-1', 25 | 'label': '节点1-1', 26 | }, 27 | { 28 | 'value': '节点1-2', 29 | 'label': '节点1-2', 30 | 'children': [ 31 | { 32 | 'value': '节点1-2-1', 33 | 'label': '节点1-2-1', 34 | }, 35 | { 36 | 'value': '节点1-2-2', 37 | 'label': '节点1-2-2', 38 | }, 39 | ], 40 | }, 41 | ], 42 | }, 43 | { 44 | 'value': '节点2', 45 | 'label': '节点2', 46 | 'children': [ 47 | { 48 | 'value': '节点2-1', 49 | 'label': '节点2-1', 50 | }, 51 | { 52 | 'value': '节点2-2', 53 | 'label': '节点2-2', 54 | }, 55 | ], 56 | }, 57 | ], 58 | readOnly=True, 59 | value=[ 60 | ['节点1', '节点1-1'], 61 | ['节点2', '节点2-1'], 62 | ], 63 | multiple=True, 64 | style=style(width=300), 65 | ) 66 | ], 67 | direction='vertical', 68 | ) 69 | ], 70 | style={'padding': 100}, 71 | ) 72 | 73 | if __name__ == '__main__': 74 | app.run(debug=True) 75 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDatePicker/feat_custom_cells.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdText('日期:精确匹配'), 16 | fac.AntdDatePicker( 17 | style={'width': 200}, 18 | customCells=[ 19 | { 20 | 'year': 2024, 21 | 'month': 9, 22 | 'date': 4, 23 | 'style': { 24 | 'border': '1px solid #389e0d', 25 | 'borderRadius': '50%', 26 | }, 27 | } 28 | ], 29 | ), 30 | fac.AntdText('日期:年份通配'), 31 | fac.AntdDatePicker( 32 | style={'width': 200}, 33 | customCells=[ 34 | { 35 | 'month': 9, 36 | 'date': 4, 37 | 'style': { 38 | 'border': '1px solid #389e0d', 39 | 'borderRadius': '50%', 40 | }, 41 | } 42 | ], 43 | ), 44 | fac.AntdText('日期:月份通配'), 45 | fac.AntdDatePicker( 46 | style={'width': 200}, 47 | customCells=[ 48 | { 49 | 'year': 2024, 50 | 'date': 4, 51 | 'style': { 52 | 'border': '1px solid #389e0d', 53 | 'borderRadius': '50%', 54 | }, 55 | } 56 | ], 57 | ), 58 | fac.AntdText('日期:年份+月份通配'), 59 | fac.AntdDatePicker( 60 | style={'width': 200}, 61 | customCells=[ 62 | { 63 | 'date': 4, 64 | 'style': { 65 | 'border': '1px solid #389e0d', 66 | 'borderRadius': '50%', 67 | }, 68 | } 69 | ], 70 | ), 71 | ], 72 | direction='vertical', 73 | ) 74 | ], 75 | style={'padding': 100}, 76 | ) 77 | 78 | if __name__ == '__main__': 79 | app.run(debug=True) 80 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDatePicker/feat_picker_value.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdDatePicker( 17 | id='date-picker-demo', 18 | style={'width': 200}, 19 | ), 20 | fac.AntdText(id='picker-value'), 21 | ], 22 | direction='vertical', 23 | ) 24 | ], 25 | style={'padding': 100}, 26 | ) 27 | 28 | 29 | @app.callback( 30 | Output('picker-value', 'children'), 31 | Input('date-picker-demo', 'pickerValue'), 32 | ) 33 | def show_picker_value(pickerValue): 34 | return pickerValue 35 | 36 | 37 | if __name__ == '__main__': 38 | app.run(debug=True) 39 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDatePicker/feat_prefix.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdDatePicker( 14 | prefix=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDatePicker/feat_suffix_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdDatePicker( 14 | suffixIcon=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDateRangePicker/feat_custom_cells.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdText('日期:精确匹配'), 16 | fac.AntdDateRangePicker( 17 | style={'width': 200}, 18 | customCells=[ 19 | { 20 | 'year': 2024, 21 | 'month': 9, 22 | 'date': 4, 23 | 'style': { 24 | 'border': '1px solid #389e0d', 25 | 'borderRadius': '50%', 26 | }, 27 | } 28 | ], 29 | ), 30 | fac.AntdText('日期:年份通配'), 31 | fac.AntdDateRangePicker( 32 | style={'width': 200}, 33 | customCells=[ 34 | { 35 | 'month': 9, 36 | 'date': 4, 37 | 'style': { 38 | 'border': '1px solid #389e0d', 39 | 'borderRadius': '50%', 40 | }, 41 | } 42 | ], 43 | ), 44 | fac.AntdText('日期:月份通配'), 45 | fac.AntdDateRangePicker( 46 | style={'width': 200}, 47 | customCells=[ 48 | { 49 | 'year': 2024, 50 | 'date': 4, 51 | 'style': { 52 | 'border': '1px solid #389e0d', 53 | 'borderRadius': '50%', 54 | }, 55 | } 56 | ], 57 | ), 58 | fac.AntdText('日期:年份+月份通配'), 59 | fac.AntdDateRangePicker( 60 | style={'width': 200}, 61 | customCells=[ 62 | { 63 | 'date': 4, 64 | 'style': { 65 | 'border': '1px solid #389e0d', 66 | 'borderRadius': '50%', 67 | }, 68 | } 69 | ], 70 | ), 71 | ], 72 | direction='vertical', 73 | ) 74 | ], 75 | style={'padding': 100}, 76 | ) 77 | 78 | if __name__ == '__main__': 79 | app.run(debug=True) 80 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDateRangePicker/feat_picker_value.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdDateRangePicker( 17 | id='date-range-picker-demo', 18 | style={'width': 250}, 19 | ), 20 | fac.AntdText(id='picker-value'), 21 | ], 22 | direction='vertical', 23 | ) 24 | ], 25 | style={'padding': 100}, 26 | ) 27 | 28 | 29 | @app.callback( 30 | Output('picker-value', 'children'), 31 | Input('date-range-picker-demo', 'pickerValue'), 32 | ) 33 | def show_picker_value(pickerValue): 34 | return str(pickerValue) 35 | 36 | 37 | if __name__ == '__main__': 38 | app.run(debug=True) 39 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDateRangePicker/feat_prefix.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdDateRangePicker( 14 | prefix=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdDateRangePicker/feat_suffix_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdDateRangePicker( 14 | suffixIcon=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdForm/feat_optional_batch_control.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import json 6 | import dash 7 | from dash import html 8 | import feffery_antd_components as fac 9 | from dash.dependencies import Input, Output 10 | from feffery_dash_utils.style_utils import style 11 | 12 | app = dash.Dash(__name__) 13 | 14 | app.layout = html.Div( 15 | [ 16 | fac.AntdSpace( 17 | [ 18 | fac.AntdForm( 19 | [ 20 | fac.AntdFormItem( 21 | fac.AntdInput( 22 | name=f'表单项{i}', 23 | enableBatchControl=i % 2 24 | == 0, 25 | ), 26 | label=f'表单项{i}', 27 | ) 28 | for i in range(1, 6) 29 | ], 30 | id='callback-listen-value-form-demo', 31 | enableBatchControl=True, 32 | layout='vertical', 33 | values={ 34 | f'表单项{i}': f'这是表单项{i}的设定值' 35 | for i in range(1, 6) 36 | if i % 2 == 0 37 | }, 38 | ), 39 | html.Pre( 40 | id='callback-listen-value-form-demo-output' 41 | ), 42 | ], 43 | direction='vertical', 44 | style={'width': '100%'}, 45 | ) 46 | ], 47 | style=style(padding=50), 48 | ) 49 | 50 | 51 | @app.callback( 52 | Output( 53 | 'callback-listen-value-form-demo-output', 'children' 54 | ), 55 | Input('callback-listen-value-form-demo', 'values'), 56 | ) 57 | def callback_listen_value_demo(values): 58 | return json.dumps(values, ensure_ascii=False, indent=4) 59 | 60 | 61 | if __name__ == '__main__': 62 | app.run(debug=True) 63 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdForm/fix_checkbox.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdForm( 15 | [ 16 | fac.AntdFormItem( 17 | fac.AntdInput( 18 | id='login-user-name', 19 | placeholder='请输入用户名', 20 | size='large', 21 | prefix=fac.AntdIcon( 22 | icon='antd-user', 23 | className='global-help-text', 24 | ), 25 | autoComplete='off', 26 | ), 27 | label='用户名', 28 | ), 29 | fac.AntdFormItem( 30 | fac.AntdInput( 31 | id='login-password', 32 | placeholder='请输入密码', 33 | size='large', 34 | mode='password', 35 | prefix=fac.AntdIcon( 36 | icon='antd-lock', 37 | className='global-help-text', 38 | ), 39 | ), 40 | label='密码', 41 | ), 42 | fac.AntdCheckbox( 43 | id='login-remember-me', label='记住我' 44 | ), 45 | fac.AntdButton( 46 | '登录', 47 | id='login-button', 48 | loadingChildren='校验中', 49 | type='primary', 50 | block=True, 51 | size='large', 52 | style=style(marginTop=18), 53 | ), 54 | ], 55 | id='login-form', 56 | enableBatchControl=True, 57 | layout='vertical', 58 | style=style(width=350), 59 | ) 60 | ], 61 | style={'padding': 100}, 62 | ) 63 | 64 | if __name__ == '__main__': 65 | app.run(debug=True) 66 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdRadioGroup/feat_block.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdSpace( 13 | [ 14 | fac.AntdRadioGroup( 15 | options=['Apple', 'Pear', 'Orange'], 16 | block=True, 17 | value='Apple', 18 | ), 19 | fac.AntdRadioGroup( 20 | options=['Apple', 'Pear', 'Orange'], 21 | block=True, 22 | optionType='button', 23 | value='Apple', 24 | ), 25 | fac.AntdRadioGroup( 26 | options=['Apple', 'Pear', 'Orange'], 27 | block=True, 28 | optionType='button', 29 | buttonStyle='solid', 30 | value='Apple', 31 | ), 32 | ], 33 | direction='vertical', 34 | style=style(width='100%'), 35 | ), 36 | style=style(height='100vh'), 37 | ) 38 | 39 | if __name__ == '__main__': 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdSelect/feat_locale_ru.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdSelect( 15 | options=[], 16 | locale='ru-ru', 17 | style=style(width=200), 18 | ) 19 | ], 20 | style=style(padding=50), 21 | ) 22 | 23 | if __name__ == '__main__': 24 | app.run(debug=True) 25 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdSelect/feat_max_count.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSelect( 14 | prefix='至多选择3个', 15 | options=[ 16 | {'label': f'选项{i}', 'value': f'选项{i}'} 17 | for i in range(1, 26) 18 | ], 19 | maxCount=3, 20 | mode='multiple', 21 | style={'width': 350}, 22 | ) 23 | ], 24 | style={'padding': 100}, 25 | ) 26 | 27 | if __name__ == '__main__': 28 | app.run(debug=True) 29 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdSelect/feat_prefix.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSelect( 14 | options=[ 15 | {'label': f'选项{i}', 'value': f'选项{i}'} 16 | for i in range(1, 6) 17 | ], 18 | prefix=fac.AntdIcon(icon='antd-user'), 19 | style={'width': 350}, 20 | ) 21 | ], 22 | style={'padding': 100}, 23 | ) 24 | 25 | if __name__ == '__main__': 26 | app.run(debug=True) 27 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdSelect/feat_suffix_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdSelect( 16 | options=[ 17 | { 18 | 'label': f'选项{i}', 19 | 'value': f'选项{i}', 20 | } 21 | for i in range(1, 6) 22 | ], 23 | style={'width': 350}, 24 | ), 25 | fac.AntdSelect( 26 | options=[ 27 | { 28 | 'label': f'选项{i}', 29 | 'value': f'选项{i}', 30 | } 31 | for i in range(1, 6) 32 | ], 33 | suffixIcon=fac.AntdIcon( 34 | icon='antd-user' 35 | ), 36 | style={'width': 350}, 37 | ), 38 | ], 39 | direction='vertical', 40 | ) 41 | ], 42 | style={'padding': 100}, 43 | ) 44 | 45 | if __name__ == '__main__': 46 | app.run(debug=True) 47 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdSelect/fix_read_only.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdSelect( 16 | readOnly=True, 17 | options=[ 18 | f'选项{i}' for i in range(1, 6) 19 | ], 20 | value='选项1', 21 | style={'width': '100%'}, 22 | ), 23 | fac.AntdSelect( 24 | readOnly=True, 25 | mode='multiple', 26 | options=[ 27 | f'选项{i}' for i in range(1, 6) 28 | ], 29 | value=[f'选项{i}' for i in range(1, 3)], 30 | style={'width': '100%'}, 31 | ), 32 | fac.AntdSelect( 33 | readOnly=True, 34 | mode='tags', 35 | options=[ 36 | f'选项{i}' for i in range(1, 6) 37 | ], 38 | value=['选项1', '自由新增选项'], 39 | style={'width': '100%'}, 40 | ), 41 | ], 42 | direction='vertical', 43 | style={'width': 350}, 44 | ) 45 | ], 46 | style={'padding': 100}, 47 | ) 48 | 49 | if __name__ == '__main__': 50 | app.run(debug=True) 51 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTimePicker/feat_prefix.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdTimePicker( 14 | prefix=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTimePicker/feat_suffix_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdTimePicker( 14 | suffixIcon=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTimeRangePicker/feat_prefix.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdTimeRangePicker( 14 | prefix=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTimeRangePicker/feat_suffix_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdTimeRangePicker( 14 | suffixIcon=fac.AntdIcon(icon='antd-user') 15 | ) 16 | ], 17 | style={'padding': 100}, 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTreeSelect/feat_async_data_load.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import time 6 | import dash 7 | from dash import html 8 | import feffery_antd_components as fac 9 | from feffery_dash_utils.tree_utils import TreeManager 10 | from dash.dependencies import Input, Output, State 11 | 12 | app = dash.Dash(__name__) 13 | 14 | app.layout = html.Div( 15 | [ 16 | fac.AntdTreeSelect( 17 | id='tree-select-demo', 18 | treeData=[ 19 | { 20 | 'key': '节点1', 21 | 'title': '节点1', 22 | 'value': '节点1', 23 | }, 24 | { 25 | 'key': '节点2', 26 | 'title': '节点2', 27 | 'value': '节点2', 28 | }, 29 | { 30 | 'key': '节点3', 31 | 'title': '节点3', 32 | 'value': '节点3', 33 | 'isLeaf': True, 34 | }, 35 | ], 36 | enableAsyncLoad=True, 37 | style={'width': 300}, 38 | ) 39 | ], 40 | style={'padding': 100}, 41 | ) 42 | 43 | 44 | @app.callback( 45 | Output('tree-select-demo', 'treeData'), 46 | Input('tree-select-demo', 'loadingNode'), 47 | State('tree-select-demo', 'treeData'), 48 | prevent_initial_call=True, 49 | ) 50 | def tree_select_demo(loadingNode, treeData): 51 | time.sleep(0.5) 52 | return TreeManager.update_tree_node( 53 | treeData, 54 | node_key=loadingNode['key'], 55 | new_node={ 56 | 'children': [ 57 | { 58 | 'key': loadingNode['key'] + '-1', 59 | 'title': loadingNode['key'] + '-1', 60 | 'value': loadingNode['key'] + '-1', 61 | } 62 | ] 63 | }, 64 | mode='overlay', 65 | ) 66 | 67 | 68 | if __name__ == '__main__': 69 | app.run(debug=True) 70 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTreeSelect/feat_max_count.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | from dash.dependencies import Input, Output 8 | import feffery_antd_components as fac 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTreeSelect( 15 | id='test-max-count-demo', 16 | treeData=[ 17 | { 18 | 'key': '节点1', 19 | 'value': '1', 20 | 'title': '节点1', 21 | 'children': [ 22 | { 23 | 'key': f'节点1-{i}', 24 | 'value': f'1-{i}', 25 | 'title': f'节点1-{i}', 26 | } 27 | for i in range(1, 3) 28 | ], 29 | }, 30 | { 31 | 'key': '节点2', 32 | 'value': '2', 33 | 'title': '节点2', 34 | 'children': [ 35 | { 36 | 'key': f'节点2-{i}', 37 | 'value': f'2-{i}', 38 | 'title': f'节点2-{i}', 39 | } 40 | for i in range(1, 5) 41 | ], 42 | }, 43 | ], 44 | placeholder='请选择', 45 | multiple=True, 46 | treeCheckable=True, 47 | showCheckedStrategy='show-child', 48 | maxCount=3, 49 | style={'width': 256}, 50 | ) 51 | ], 52 | style={'padding': 100}, 53 | ) 54 | 55 | 56 | @app.callback( 57 | Output('test-max-count-demo', 'suffixIcon'), 58 | Input('test-max-count-demo', 'value'), 59 | ) 60 | def test_max_count_demo(value): 61 | length = 0 62 | if value: 63 | length = len(value) 64 | return [ 65 | html.Span(f'{length} / 3'), 66 | fac.AntdIcon(icon='antd-down') 67 | ] 68 | 69 | 70 | if __name__ == '__main__': 71 | app.run(debug=True) 72 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTreeSelect/feat_prefix.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdTreeSelect( 14 | treeData=[ 15 | { 16 | 'key': '节点1', 17 | 'value': '1', 18 | 'title': '节点1', 19 | 'children': [ 20 | { 21 | 'key': f'节点1-{i}', 22 | 'value': f'1-{i}', 23 | 'title': f'节点1-{i}', 24 | } 25 | for i in range(1, 5) 26 | ], 27 | }, 28 | { 29 | 'key': '节点2', 30 | 'value': '2', 31 | 'title': '节点2', 32 | }, 33 | ], 34 | placeholder='请选择', 35 | prefix=fac.AntdIcon(icon='antd-user'), 36 | style={'width': 256}, 37 | ) 38 | ], 39 | style={'padding': 100}, 40 | ) 41 | 42 | if __name__ == '__main__': 43 | app.run(debug=True) 44 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdTreeSelect/fix_read_only.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdTreeSelect( 16 | treeData=[ 17 | { 18 | 'key': '节点1', 19 | 'value': '1', 20 | 'title': '节点1', 21 | 'children': [ 22 | { 23 | 'key': f'节点1-{i}', 24 | 'value': f'1-{i}', 25 | 'title': f'节点1-{i}', 26 | } 27 | for i in range(1, 5) 28 | ], 29 | }, 30 | { 31 | 'key': '节点2', 32 | 'value': '2', 33 | 'title': '节点2', 34 | }, 35 | ], 36 | placeholder='请选择', 37 | defaultValue=['节点2', '节点1-2'], 38 | readOnly=True, 39 | multiple=True, 40 | style={'width': 256}, 41 | ) 42 | ], 43 | direction='vertical', 44 | ) 45 | ], 46 | style={'padding': 100}, 47 | ) 48 | 49 | if __name__ == '__main__': 50 | app.run(debug=True) 51 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdUpload/feat_pastable.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdUpload( 15 | buttonContent='upload test', pastable=True 16 | ) 17 | ], 18 | style=style(padding=50), 19 | ) 20 | 21 | if __name__ == '__main__': 22 | app.run(debug=True) 23 | -------------------------------------------------------------------------------- /tests/dataEntry/AntdUpload/fix_follow_theme.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdConfigProvider( 15 | [ 16 | fac.AntdUpload( 17 | buttonContent='upload test', 18 | confirmBeforeDelete=True, 19 | ) 20 | ], 21 | algorithm='dark', 22 | ) 23 | ], 24 | style=style(padding=50), 25 | ) 26 | 27 | if __name__ == '__main__': 28 | app.run(debug=True) 29 | -------------------------------------------------------------------------------- /tests/feedback/AntdAlert/feat_icon.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdAlert( 16 | message='test alert', 17 | type='info', 18 | showIcon=True, 19 | icon='😀', 20 | ), 21 | fac.AntdAlert( 22 | message='test alert', 23 | type='info', 24 | showIcon=True, 25 | icon=fac.AntdIcon(icon='fc-like'), 26 | ), 27 | ], 28 | direction='vertical', 29 | style=style(width='100%'), 30 | ), 31 | style=style(padding=50), 32 | ) 33 | 34 | if __name__ == '__main__': 35 | app.run(debug=True) 36 | -------------------------------------------------------------------------------- /tests/feedback/AntdMessage/fix_follow_config_provider.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | fac.AntdConfigProvider( 15 | [ 16 | fac.AntdButton( 17 | 'new message', 18 | id='new-message', 19 | type='primary', 20 | ), 21 | fac.Fragment(id='message-target'), 22 | ], 23 | algorithm='dark', 24 | ), 25 | style=style(padding=50), 26 | ) 27 | 28 | 29 | @app.callback( 30 | Output('message-target', 'children'), 31 | Input('new-message', 'nClicks'), 32 | prevent_initial_call=True, 33 | ) 34 | def new_message(nClicks): 35 | return fac.AntdMessage( 36 | content=f'nClicks: {nClicks}', 37 | type='info', 38 | top=256, 39 | maxCount=3, 40 | ) 41 | 42 | 43 | if __name__ == '__main__': 44 | app.run(debug=True) 45 | -------------------------------------------------------------------------------- /tests/feedback/AntdModal/feat_force_render.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | from dash.dependencies import Input, Output 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | [ 15 | fac.AntdModal( 16 | fac.AntdInput( 17 | id='modal-demo1-input', defaultValue='demo1' 18 | ), 19 | id='modal-demo1', 20 | ), 21 | fac.AntdModal( 22 | fac.AntdInput( 23 | id='modal-demo2-input', defaultValue='demo2' 24 | ), 25 | id='modal-demo2', 26 | forceRender=True, 27 | ), 28 | fac.AntdSpace( 29 | [ 30 | fac.AntdText(id='demo1-output'), 31 | fac.AntdText(id='demo2-output'), 32 | ], 33 | direction='vertical', 34 | ), 35 | ], 36 | style=style(padding=50), 37 | ) 38 | 39 | 40 | @app.callback( 41 | Output('demo1-output', 'children'), 42 | Input('modal-demo1-input', 'value'), 43 | ) 44 | def demo1_output(value): 45 | return value 46 | 47 | 48 | @app.callback( 49 | Output('demo2-output', 'children'), 50 | Input('modal-demo2-input', 'value'), 51 | ) 52 | def demo2_output(value): 53 | return value 54 | 55 | 56 | if __name__ == '__main__': 57 | app.run(debug=True) 58 | -------------------------------------------------------------------------------- /tests/feedback/AntdModal/feat_responsive_width.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdModal( 15 | title='test modal', 16 | visible=True, 17 | width={ 18 | 'xs': '100vw', 19 | 'sm': '100vw', 20 | 'md': '100vw', 21 | 'lg': 500, 22 | 'xl': 500, 23 | 'xxl': 500, 24 | }, 25 | ) 26 | ], 27 | style=style(padding=50), 28 | ) 29 | 30 | if __name__ == '__main__': 31 | app.run(debug=True) 32 | -------------------------------------------------------------------------------- /tests/feedback/AntdNotification/feat_show_progress.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | [ 15 | fac.AntdButton( 16 | '新的通知', 17 | id='new-notification', 18 | type='primary', 19 | ), 20 | fac.Fragment(id='notification-target'), 21 | ], 22 | style=style(padding=50), 23 | ) 24 | 25 | 26 | @app.callback( 27 | Output('notification-target', 'children'), 28 | Input('new-notification', 'nClicks'), 29 | prevent_initial_call=True, 30 | ) 31 | def new_notification(nClicks): 32 | return fac.AntdNotification( 33 | message='通知标题', 34 | description='通知描述', 35 | stack=True, 36 | ) 37 | 38 | 39 | if __name__ == '__main__': 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /tests/feedback/AntdNotification/fix_follow_config_provider.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | fac.AntdConfigProvider( 15 | [ 16 | fac.AntdButton( 17 | 'new notification', 18 | id='new-notification', 19 | type='primary', 20 | ), 21 | fac.Fragment(id='notification-target'), 22 | ], 23 | algorithm='dark', 24 | ), 25 | style=style(padding=50), 26 | ) 27 | 28 | 29 | @app.callback( 30 | Output('notification-target', 'children'), 31 | Input('new-notification', 'nClicks'), 32 | prevent_initial_call=True, 33 | ) 34 | def new_notification(nClicks): 35 | return fac.AntdNotification( 36 | message='通知标题', 37 | description='通知描述', 38 | type='info', 39 | stack=True, 40 | showProgress=True, 41 | pauseOnHover=True, 42 | ) 43 | 44 | 45 | if __name__ == '__main__': 46 | app.run(debug=True) 47 | -------------------------------------------------------------------------------- /tests/feedback/AntdPopupCard/feat_force_render.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | from dash.dependencies import Input, Output 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | [ 15 | fac.AntdPopupCard( 16 | fac.AntdInput( 17 | id='popup-card-demo1-input', 18 | defaultValue='demo1', 19 | ), 20 | id='popup-card-demo1', 21 | visible=False, 22 | ), 23 | fac.AntdPopupCard( 24 | fac.AntdInput( 25 | id='popup-card-demo2-input', 26 | defaultValue='demo2', 27 | ), 28 | id='popup-card-demo2', 29 | visible=False, 30 | forceRender=True, 31 | ), 32 | fac.AntdSpace( 33 | [ 34 | fac.AntdText(id='demo1-output'), 35 | fac.AntdText(id='demo2-output'), 36 | ], 37 | direction='vertical', 38 | ), 39 | ], 40 | style=style(padding=50), 41 | ) 42 | 43 | 44 | @app.callback( 45 | Output('demo1-output', 'children'), 46 | Input('popup-card-demo1-input', 'value'), 47 | ) 48 | def demo1_output(value): 49 | return value 50 | 51 | 52 | @app.callback( 53 | Output('demo2-output', 'children'), 54 | Input('popup-card-demo2-input', 'value'), 55 | ) 56 | def demo2_output(value): 57 | return value 58 | 59 | 60 | if __name__ == '__main__': 61 | app.run(debug=True) 62 | -------------------------------------------------------------------------------- /tests/feedback/AntdResult/feat_extra.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdResult( 15 | title='404', 16 | subTitle='Sorry, the page you visited does not exist.', 17 | extra=fac.AntdButton( 18 | 'Back Home', type='primary' 19 | ), 20 | ) 21 | ], 22 | style=style(padding=50), 23 | ) 24 | 25 | if __name__ == '__main__': 26 | app.run(debug=True) 27 | -------------------------------------------------------------------------------- /tests/general/AntdButton/feat_color_and_variant.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdCenter( 12 | fac.AntdSpace( 13 | [ 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdButton( 17 | variant, 18 | color=color, 19 | variant=variant, 20 | size='small', 21 | ) 22 | for variant in [ 23 | 'outlined', 24 | 'dashed', 25 | 'solid', 26 | 'filled', 27 | 'text', 28 | 'link', 29 | ] 30 | ] 31 | ) 32 | for color in ['default', 'primary', 'danger'] 33 | ], 34 | direction='vertical', 35 | ), 36 | style=style(height='100vh'), 37 | ) 38 | 39 | if __name__ == '__main__': 40 | app.run(debug=True) 41 | -------------------------------------------------------------------------------- /tests/general/AntdButton/feat_preset_color.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdButton( 16 | color, 17 | color=color, 18 | size='small', 19 | variant='solid', 20 | ) 21 | for color in [ 22 | 'default', 23 | 'primary', 24 | 'danger', 25 | 'blue', 26 | 'purple', 27 | 'cyan', 28 | 'green', 29 | 'magenta', 30 | 'pink', 31 | 'red', 32 | 'orange', 33 | 'yellow', 34 | 'volcano', 35 | 'geekblue', 36 | 'lime', 37 | 'gold', 38 | ] 39 | ], 40 | direction='vertical', 41 | ), 42 | style=style(padding=50), 43 | ) 44 | 45 | if __name__ == '__main__': 46 | app.run(debug=True) 47 | -------------------------------------------------------------------------------- /tests/general/AntdFloatButtonGroup/feat_placement.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdFloatButtonGroup( 15 | [ 16 | fac.AntdFloatButton( 17 | icon=fac.AntdIcon(icon='antd-question') 18 | ), 19 | fac.AntdFloatButton( 20 | icon=fac.AntdIcon(icon='antd-setting') 21 | ), 22 | ], 23 | icon=fac.AntdIcon(icon='antd-up'), 24 | trigger='click', 25 | placement='top', 26 | style=style( 27 | bottom='calc(50% + 50px)', right='50%' 28 | ), 29 | ), 30 | fac.AntdFloatButtonGroup( 31 | [ 32 | fac.AntdFloatButton( 33 | icon=fac.AntdIcon(icon='antd-question') 34 | ), 35 | fac.AntdFloatButton( 36 | icon=fac.AntdIcon(icon='antd-setting') 37 | ), 38 | ], 39 | icon=fac.AntdIcon(icon='antd-right'), 40 | trigger='click', 41 | placement='right', 42 | style=style( 43 | bottom='50%', right='calc(50% - 50px)' 44 | ), 45 | ), 46 | fac.AntdFloatButtonGroup( 47 | [ 48 | fac.AntdFloatButton( 49 | icon=fac.AntdIcon(icon='antd-question') 50 | ), 51 | fac.AntdFloatButton( 52 | icon=fac.AntdIcon(icon='antd-setting') 53 | ), 54 | ], 55 | icon=fac.AntdIcon(icon='antd-down'), 56 | trigger='click', 57 | placement='bottom', 58 | style=style( 59 | bottom='calc(50% - 50px)', right='50%' 60 | ), 61 | ), 62 | fac.AntdFloatButtonGroup( 63 | [ 64 | fac.AntdFloatButton( 65 | icon=fac.AntdIcon(icon='antd-question') 66 | ), 67 | fac.AntdFloatButton( 68 | icon=fac.AntdIcon(icon='antd-setting') 69 | ), 70 | ], 71 | icon=fac.AntdIcon(icon='antd-left'), 72 | trigger='click', 73 | placement='left', 74 | style=style( 75 | bottom='50%', right='calc(50% + 50px)' 76 | ), 77 | ), 78 | ], 79 | style=style(position='relative', height='100vh'), 80 | ) 81 | 82 | if __name__ == '__main__': 83 | app.run(debug=True) 84 | -------------------------------------------------------------------------------- /tests/general/AntdFloatButtonGroup/feat_tooltip.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdFloatButtonGroup( 15 | [ 16 | fac.AntdFloatButton( 17 | tooltip='气泡卡片信息示例' 18 | ), 19 | fac.AntdFloatButton( 20 | tooltip={ 21 | 'title': '气泡卡片信息示例', 22 | 'color': 'blue', 23 | 'placement': 'left', 24 | } 25 | ), 26 | ], 27 | style=style(right=100), 28 | ) 29 | ], 30 | style=style(position='relative', height='100vh'), 31 | ) 32 | 33 | if __name__ == '__main__': 34 | app.run(debug=True) 35 | -------------------------------------------------------------------------------- /tests/general/AntdIcon/feat_iconfont.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = dash.Dash(__name__) 10 | 11 | app.layout = fac.AntdSpace( 12 | [ 13 | fac.AntdIcon(icon='antd-bug'), 14 | fac.AntdIcon( 15 | mode='iconfont', 16 | scriptUrl='//at.alicdn.com/t/font_8d5l8fzk5b87iudi.js', 17 | icon='icon-facebook', 18 | style=style(color='#1877F2'), 19 | ), 20 | *[ 21 | fac.AntdIcon( 22 | mode='iconfont', 23 | scriptUrl=[ 24 | '//at.alicdn.com/t/font_1788044_0dwu4guekcwr.js', 25 | '//at.alicdn.com/t/font_1788592_a5xf2bdic3u.js', 26 | ], 27 | icon=icon, 28 | ) 29 | for icon in [ 30 | 'icon-javascript', 31 | 'icon-java', 32 | 'icon-shoppingcart', 33 | 'icon-python', 34 | ] 35 | ], 36 | ], 37 | style=style(padding=50), 38 | ) 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | -------------------------------------------------------------------------------- /tests/layout/AntdCenter/feat_use_token.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | import feffery_antd_components as fac 7 | from dash.dependencies import Input, Output 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = fac.AntdConfigProvider( 13 | fac.AntdCenter( 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdSwitch( 17 | id='switch-theme', 18 | checked=True, 19 | checkedChildren='dark', 20 | unCheckedChildren='default', 21 | ), 22 | '测试', 23 | ], 24 | direction='vertical', 25 | align='center', 26 | ), 27 | style=style(height='100vh'), 28 | ), 29 | id='config-provider', 30 | algorithm='dark', 31 | token={'fontSize': 18}, 32 | ) 33 | 34 | app.clientside_callback( 35 | '(checked) => checked ? "dark" : "default"', 36 | Output('config-provider', 'algorithm'), 37 | Input('switch-theme', 'checked'), 38 | ) 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | -------------------------------------------------------------------------------- /tests/layout/AntdDivider/feat_plain.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdDivider('plain=True'), 15 | fac.AntdDivider('plain=False', plain=False), 16 | ], 17 | style=style(padding=50), 18 | ) 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True) 22 | -------------------------------------------------------------------------------- /tests/layout/AntdDivider/feat_size.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdTabs( 15 | items=[ 16 | { 17 | 'label': size, 18 | 'key': size, 19 | 'children': [ 20 | 'test content', 21 | fac.AntdDivider(size=size), 22 | 'test content', 23 | fac.AntdDivider(size=size), 24 | 'test content', 25 | ], 26 | } 27 | for size in ['small', 'middle', 'large'] 28 | ], 29 | centered=True, 30 | ) 31 | ], 32 | style=style(padding=50), 33 | ) 34 | 35 | if __name__ == '__main__': 36 | app.run(debug=True) 37 | -------------------------------------------------------------------------------- /tests/layout/AntdSplitter/feat_lazy.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | from dash import Dash, html 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdSpace( 14 | [ 15 | fac.AntdSplitter( 16 | items=[ 17 | { 18 | 'children': fac.AntdCenter( 19 | f'item{i}', 20 | style={'height': '100%'}, 21 | ) 22 | } 23 | for i in range(1, 3) 24 | ], 25 | lazy=True, 26 | style={ 27 | 'height': 200, 28 | 'boxShadow': '0 0 10px rgba(0, 0, 0, 0.1)', 29 | }, 30 | ), 31 | fac.AntdSplitter( 32 | items=[ 33 | { 34 | 'children': fac.AntdCenter( 35 | f'item{i}', 36 | style={'height': '100%'}, 37 | ) 38 | } 39 | for i in range(1, 4) 40 | ], 41 | lazy=True, 42 | style={ 43 | 'height': 200, 44 | 'boxShadow': '0 0 10px rgba(0, 0, 0, 0.1)', 45 | }, 46 | ), 47 | ], 48 | direction='vertical', 49 | style={'width': '100%'}, 50 | ) 51 | ], 52 | style=style(padding=50), 53 | ) 54 | 55 | if __name__ == '__main__': 56 | app.run(debug=True) 57 | -------------------------------------------------------------------------------- /tests/navigation/AntdBreadcrumb/feat_menu_item_event.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import json 6 | from dash import Dash, html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | [ 15 | fac.AntdSpace( 16 | [ 17 | fac.AntdBreadcrumb( 18 | id='breadcrumnb-demo', 19 | items=[ 20 | {'title': '首页', 'key': '首页'}, 21 | { 22 | 'title': '下属页面1', 23 | 'key': '下属页面1', 24 | 'menuItems': [ 25 | { 26 | 'key': f'子节点{i}', 27 | 'title': f'子节点{i}', 28 | 'icon': 'antd-smile', 29 | } 30 | for i in range(1, 4) 31 | ], 32 | }, 33 | { 34 | 'title': '下属页面1-1', 35 | 'key': '下属页面1-1', 36 | }, 37 | ], 38 | ), 39 | html.Pre(id='breadcrumnb-demo-output'), 40 | ], 41 | size=50, 42 | direction='vertical', 43 | style=style(width='100%'), 44 | ) 45 | ], 46 | style=style(padding=50), 47 | ) 48 | 49 | 50 | @app.callback( 51 | Output('breadcrumnb-demo-output', 'children'), 52 | Input('breadcrumnb-demo', 'clickedItem'), 53 | prevent_initial_call=True, 54 | ) 55 | def breadcrumb_callback_demo(clickedItem): 56 | return json.dumps( 57 | dict(clickedItem=clickedItem), 58 | indent=4, 59 | ensure_ascii=False, 60 | ) 61 | 62 | 63 | if __name__ == '__main__': 64 | app.run(debug=True) 65 | -------------------------------------------------------------------------------- /tests/navigation/AntdDropdown/feat_extra.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | from dash import Dash, html 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdDropdown( 14 | title='触发点', 15 | menuItems=[ 16 | {'title': '选项1', 'extra': '测试'}, 17 | {'title': '选项2', 'extra': '测试'}, 18 | {'isDivider': True}, 19 | {'title': '选项3-1', 'extra': '测试'}, 20 | {'title': '选项3-2', 'extra': '测试'}, 21 | ], 22 | ) 23 | ], 24 | style=style(padding=50), 25 | ) 26 | 27 | 28 | if __name__ == '__main__': 29 | app.run(debug=True) 30 | -------------------------------------------------------------------------------- /tests/navigation/AntdMenu/feat_triggerSubMenuAction.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | from dash import Dash, html 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | html.Div( 14 | [ 15 | fac.AntdDivider( 16 | f'mode="{mode}"', 17 | innerTextOrientation='left', 18 | ), 19 | fac.AntdMenu( 20 | menuItems=[ 21 | { 22 | 'component': 'SubMenu', 23 | 'props': { 24 | 'key': f'{sub_menu}', 25 | 'title': f'子菜单{sub_menu}', 26 | }, 27 | 'children': [ 28 | { 29 | 'component': 'ItemGroup', 30 | 'props': { 31 | 'key': f'{sub_menu}-{item_group}', 32 | 'title': f'菜单项分组{sub_menu}-{item_group}', 33 | }, 34 | 'children': [ 35 | { 36 | 'component': 'Item', 37 | 'props': { 38 | 'key': f'{sub_menu}-{item_group}-{item}', 39 | 'title': f'菜单项{sub_menu}-{item_group}-{item}', 40 | }, 41 | } 42 | for item in range( 43 | 1, 3 44 | ) 45 | ], 46 | } 47 | for item_group in range( 48 | 1, 3 49 | ) 50 | ], 51 | } 52 | for sub_menu in range(1, 5) 53 | ], 54 | mode=mode, 55 | triggerSubMenuAction='click', 56 | style={'width': 256}, 57 | ), 58 | ] 59 | ) 60 | for mode in ['vertical', 'horizontal', 'inline'] 61 | ], 62 | style=style(padding=50), 63 | ) 64 | 65 | 66 | if __name__ == '__main__': 67 | app.run(debug=True) 68 | -------------------------------------------------------------------------------- /tests/navigation/AntdMenu/fix_onlyExpandCurrentSubMenu.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | from dash import Dash, html 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdMenu( 14 | id='menu-demo', 15 | currentKey='1-1-1', 16 | menuItems=[ 17 | { 18 | 'component': 'SubMenu', 19 | 'props': { 20 | 'key': f'{sub_menu}', 21 | 'title': f'子菜单{sub_menu}', 22 | }, 23 | 'children': [ 24 | { 25 | 'component': 'ItemGroup' if item_group == 1 else 'SubMenu', 26 | 'props': { 27 | 'key': f'{sub_menu}-{item_group}', 28 | 'title': f'菜单项分组{sub_menu}-{item_group}', 29 | }, 30 | 'children': [ 31 | { 32 | 'component': 'Item', 33 | 'props': { 34 | 'key': f'{sub_menu}-{item_group}-{item}', 35 | 'title': f'菜单项{sub_menu}-{item_group}-{item}', 36 | }, 37 | 'extra': f'extra-{sub_menu}-{item_group}-{item}', 38 | } 39 | for item in range(1, 4) 40 | ], 41 | } 42 | for item_group in range(1, 4) 43 | ], 44 | } 45 | for sub_menu in range(1, 5) 46 | ], 47 | mode='inline', 48 | onlyExpandCurrentSubMenu=True, 49 | style=style(width=256), 50 | ), 51 | ], 52 | style=style(padding=50), 53 | ) 54 | 55 | 56 | if __name__ == '__main__': 57 | app.run(debug=True) 58 | -------------------------------------------------------------------------------- /tests/navigation/AntdMenu/fix_with_sider.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | from dash import Dash 6 | import feffery_antd_components as fac 7 | 8 | app = Dash(__name__) 9 | 10 | app.layout = fac.AntdLayout( 11 | [ 12 | fac.AntdSider( 13 | [ 14 | fac.AntdMenu( 15 | menuItems=[ 16 | { 17 | 'component': 'Item', 18 | 'props': { 19 | 'key': f'图标{icon}', 20 | 'title': f'图标{icon}', 21 | 'icon': icon, 22 | }, 23 | } 24 | for icon in [ 25 | 'antd-home', 26 | 'antd-cloud-upload', 27 | 'antd-bar-chart', 28 | 'antd-pie-chart', 29 | 'antd-dot-chart', 30 | 'antd-line-chart', 31 | 'antd-apartment', 32 | 'antd-app-store', 33 | 'antd-app-store-add', 34 | 'antd-bell', 35 | 'antd-calculator', 36 | 'antd-calendar', 37 | 'antd-database', 38 | 'antd-history', 39 | ] 40 | ], 41 | mode='inline', 42 | style={ 43 | 'height': '100%', 44 | 'width': '100%', 45 | 'overflow': 'hidden auto', 46 | }, 47 | ) 48 | ], 49 | collapsible=True, 50 | collapsedWidth=60, 51 | style={'backgroundColor': 'rgb(240, 242, 245)'}, 52 | ), 53 | fac.AntdContent( 54 | fac.AntdCenter( 55 | fac.AntdTitle( 56 | '内容区示例', 57 | level=2, 58 | style={'margin': '0'}, 59 | ), 60 | style={ 61 | 'height': '100%', 62 | }, 63 | ), 64 | style={'backgroundColor': 'white'}, 65 | ), 66 | ], 67 | style={'height': '100vh'}, 68 | ) 69 | 70 | if __name__ == '__main__': 71 | app.run(debug=True) 72 | -------------------------------------------------------------------------------- /tests/navigation/AntdPagination/feat_align.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | from dash import Dash, html 6 | import feffery_antd_components as fac 7 | from feffery_dash_utils.style_utils import style 8 | 9 | app = Dash(__name__) 10 | 11 | app.layout = html.Div( 12 | [ 13 | fac.AntdDivider("align='start'"), 14 | fac.AntdPagination( 15 | defaultPageSize=10, total=100, align='start' 16 | ), 17 | fac.AntdDivider("align='center'"), 18 | fac.AntdPagination( 19 | defaultPageSize=10, total=100, align='center' 20 | ), 21 | fac.AntdDivider("align='end'"), 22 | fac.AntdPagination( 23 | defaultPageSize=10, total=100, align='end' 24 | ), 25 | ], 26 | style=style(padding=50), 27 | ) 28 | 29 | 30 | if __name__ == '__main__': 31 | app.run(debug=True) 32 | -------------------------------------------------------------------------------- /tests/other/AntdAffix/feat_listen_affixed.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = html.Div( 14 | [ 15 | html.Div( 16 | fac.AntdAffix( 17 | fac.AntdButton( 18 | 'affixed: False', 19 | id='output', 20 | type='primary', 21 | ), 22 | id='affix-demo', 23 | offsetTop=24, 24 | ), 25 | style={'marginBottom': '1000px'}, 26 | ) 27 | ], 28 | style=style(padding=100, height='1000vh'), 29 | ) 30 | 31 | 32 | @app.callback( 33 | Output('output', 'children'), 34 | Input('affix-demo', 'affixed'), 35 | ) 36 | def listen_affixed(affixed): 37 | return 'affixed: True' if affixed else 'affixed: False' 38 | 39 | 40 | if __name__ == '__main__': 41 | app.run(debug=True) 42 | -------------------------------------------------------------------------------- /tests/other/AntdBackTop/refactor.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [fac.AntdBackTop()], 14 | style=style(height=9999), 15 | ) 16 | 17 | if __name__ == '__main__': 18 | app.run(debug=True) 19 | -------------------------------------------------------------------------------- /tests/other/AntdCopyText/feat_copy_table.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import io 6 | import dash 7 | import pandas as pd 8 | from dash import html 9 | import feffery_antd_components as fac 10 | from dash.dependencies import Input, Output 11 | from feffery_dash_utils.style_utils import style 12 | 13 | app = dash.Dash(__name__) 14 | 15 | app.layout = html.Div( 16 | [ 17 | fac.AntdTable( 18 | id='table', 19 | columns=[ 20 | { 21 | 'dataIndex': f'字段{i}', 22 | 'title': f'字段{i}', 23 | } 24 | for i in range(1, 6) 25 | ], 26 | data=[ 27 | { 28 | f'字段{i}': f'字段{i}第{row}行' 29 | for i in range(1, 6) 30 | } 31 | for row in range(10) 32 | ], 33 | pagination=False, 34 | bordered=True, 35 | title=fac.AntdCopyText( 36 | id='copy-table', 37 | beforeIcon=fac.AntdButton( 38 | '复制表格', type='primary' 39 | ), 40 | afterIcon=fac.AntdButton( 41 | '复制成功', type='primary' 42 | ), 43 | ), 44 | ) 45 | ], 46 | style=style(padding=50), 47 | ) 48 | 49 | 50 | @app.callback( 51 | Output('copy-table', 'text'), 52 | Input('table', 'data'), 53 | ) 54 | def generate_copy_text(data): 55 | # 将表格数据转换为可直接粘贴到excel中形成表格的字符串数据 56 | 57 | temp_io = io.StringIO() 58 | 59 | pd.DataFrame(data).to_csv( 60 | temp_io, sep='\t', index=False 61 | ) 62 | 63 | return temp_io.getvalue() 64 | 65 | 66 | if __name__ == '__main__': 67 | app.run(debug=True) 68 | -------------------------------------------------------------------------------- /tests/other/AntdCopyText/feat_tooltips.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from feffery_dash_utils.style_utils import style 9 | 10 | app = dash.Dash(__name__) 11 | 12 | app.layout = html.Div( 13 | [ 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdSpace( 17 | [ 18 | 'False', 19 | fac.AntdCopyText( 20 | text='测试', tooltips=False 21 | ), 22 | ] 23 | ), 24 | fac.AntdSpace( 25 | [ 26 | '文本', 27 | fac.AntdCopyText( 28 | text='测试', 29 | tooltips=[ 30 | '点击复制~', 31 | '复制完成~', 32 | ], 33 | ), 34 | ] 35 | ), 36 | fac.AntdSpace( 37 | [ 38 | '文本', 39 | fac.AntdCopyText( 40 | text='测试', 41 | tooltips=[ 42 | fac.AntdText( 43 | '点击复制~', strong=True 44 | ), 45 | fac.AntdText( 46 | '复制完成~', strong=True 47 | ), 48 | ], 49 | ), 50 | ] 51 | ), 52 | ], 53 | direction='vertical', 54 | style=style(width='100%'), 55 | ) 56 | ], 57 | style=style(padding=50), 58 | ) 59 | 60 | if __name__ == '__main__': 61 | app.run(debug=True) 62 | -------------------------------------------------------------------------------- /tests/other/Fragment/feat_use_token.py: -------------------------------------------------------------------------------- 1 | if True: 2 | import sys 3 | 4 | sys.path.append('../../../') 5 | import dash 6 | from dash import html 7 | import feffery_antd_components as fac 8 | from dash.dependencies import Input, Output 9 | from feffery_dash_utils.style_utils import style 10 | 11 | app = dash.Dash(__name__) 12 | 13 | app.layout = fac.AntdConfigProvider( 14 | fac.Fragment( 15 | fac.AntdCenter( 16 | html.Pre(id='show-token'), 17 | style=style(height='100vh', overflowY='auto'), 18 | ), 19 | id='listen-token', 20 | ), 21 | algorithm='dark', 22 | token={'fontSize': 18}, 23 | ) 24 | 25 | app.clientside_callback( 26 | '(token) => console.log(token)', 27 | Output('show-token', 'children'), 28 | Input('listen-token', 'token'), 29 | ) 30 | 31 | if __name__ == '__main__': 32 | app.run(debug=True) 33 | -------------------------------------------------------------------------------- /usage.py: -------------------------------------------------------------------------------- 1 | import dash 2 | from dash import html 3 | import feffery_antd_components as fac 4 | from feffery_dash_utils.style_utils import style 5 | 6 | app = dash.Dash( 7 | __name__, 8 | # 静态资源全量加载测试 9 | eager_loading=True, 10 | ) 11 | 12 | app.layout = fac.AntdConfigProvider( 13 | html.Div( 14 | fac.AntdSpace( 15 | [ 16 | fac.AntdButton( 17 | '按钮示例', type='primary', size=size 18 | ) 19 | for size in ['large', 'middle', 'small'] 20 | ], 21 | align='center', 22 | style=style( 23 | position='fixed', 24 | left='50%', 25 | top='50%', 26 | transform='translate(-50%, -50%)', 27 | ), 28 | ), 29 | style=style(padding=50), 30 | ) 31 | ) 32 | 33 | if __name__ == '__main__': 34 | app.run(debug=True) 35 | -------------------------------------------------------------------------------- /webpack.serve.config.js: -------------------------------------------------------------------------------- 1 | const config = require('./webpack.config.js'); 2 | const path = require('path'); 3 | 4 | config.entry = {main: './src/demo/index.js'}; 5 | config.output = { 6 | filename: './output.js', 7 | path: path.resolve(__dirname), 8 | }; 9 | config.mode = 'development'; 10 | config.externals = undefined; // eslint-disable-line 11 | config.devtool = 'inline-source-map'; 12 | module.exports = config; 13 | --------------------------------------------------------------------------------