├── story ├── env │ ├── index.ts │ ├── config │ │ ├── undefined.js │ │ ├── local.js │ │ └── prod.js │ └── env.d.ts ├── pages │ ├── test │ │ ├── TestGroupTransition.scss │ │ ├── TestGroupTransition.tsx │ │ └── test.vue │ ├── normal │ │ ├── DemoDialog.scss │ │ ├── DemoStep.scss │ │ ├── DemoList.scss │ │ ├── DemoScroll.scss │ │ ├── DemoGrid.scss │ │ ├── DemoRadio.scss │ │ ├── DemoIcon.tsx │ │ └── DemoCheckbox.scss │ ├── table-pro │ │ ├── table-image.tsx │ │ ├── table-files.tsx │ │ └── format-row.tsx │ ├── table │ │ └── DemoTableClassAndStyle.scss │ └── data │ │ ├── mock.js │ │ └── mock.database.js ├── components │ ├── index.ts │ ├── DemoLine.tsx │ └── DemoRow.utils.ts ├── main.tsx ├── init │ ├── useObjectOption.tsx │ ├── index.tsx │ └── useHttp.tsx ├── App.tsx ├── story.utils.ts └── app │ ├── navigator.utils.ts │ └── AppNavigator.tsx ├── .browserslistrc ├── src ├── packages │ ├── PlTime │ │ ├── panel │ │ │ ├── time.public.scss │ │ │ ├── time-range-panel.scss │ │ │ ├── time-panel.utils.ts │ │ │ ├── time-base-panel.scss │ │ │ └── time-base-column.scss │ │ ├── useTime.tsx │ │ └── time.scss │ ├── PlIcon │ │ ├── icons │ │ │ ├── el-icon-caret-top.json │ │ │ ├── el-icon-caret-right.json │ │ │ ├── el-icon-caret-left.json │ │ │ ├── el-icon-caret-bottom.json │ │ │ ├── el-icon-s-promotion.json │ │ │ ├── el-icon-s-fold.json │ │ │ ├── el-icon-s-unfold.json │ │ │ ├── el-icon-s-order.json │ │ │ ├── el-icon-minus.json │ │ │ ├── el-icon-jiahao.json │ │ │ ├── el-icon-list.json │ │ │ ├── el-icon-folder.json │ │ │ ├── el-icon-check-bold.json │ │ │ ├── el-icon-arrow-down.json │ │ │ ├── el-icon-edit.json │ │ │ ├── el-icon-arrow-left.json │ │ │ ├── el-icon-document-remove.json │ │ │ ├── el-icon-upload1.json │ │ │ ├── el-icon-folder-remove.json │ │ │ ├── el-icon-s-grid.json │ │ │ ├── el-icon-s-ticket.json │ │ │ ├── el-icon-arrow-right.json │ │ │ ├── el-icon-download.json │ │ │ ├── el-icon-plus.json │ │ │ ├── el-icon-s-custom.json │ │ │ ├── el-icon-right.json │ │ │ ├── el-icon-document-add.json │ │ │ ├── el-icon-folder-add.json │ │ │ ├── el-icon-arrow-up.json │ │ │ ├── el-icon-document.json │ │ │ ├── el-icon-top.json │ │ │ ├── el-icon-bottom.json │ │ │ ├── el-icon-position.json │ │ │ ├── el-icon-star-on.json │ │ │ ├── el-icon-document-checked.json │ │ │ ├── el-icon-bottom-left.json │ │ │ ├── el-icon-top-left.json │ │ │ ├── el-icon-upload.json │ │ │ ├── el-icon-bottom-right.json │ │ │ ├── el-icon-collection-tag.json │ │ │ ├── el-icon-folder-checked.json │ │ │ ├── el-icon-remove.json │ │ │ ├── el-icon-back.json │ │ │ ├── el-icon-s-shop.json │ │ │ ├── el-icon-top-right.json │ │ │ ├── el-icon-crop.json │ │ │ ├── el-icon-close.json │ │ │ ├── el-icon-search.json │ │ │ ├── el-icon-chat-square.json │ │ │ ├── el-icon-document-copy.json │ │ │ ├── el-icon-folder-opened.json │ │ │ ├── el-icon-more.json │ │ │ ├── el-icon-document-delete.json │ │ │ ├── el-icon-folder-delete.json │ │ │ ├── el-icon-success.json │ │ │ ├── el-icon-delete-location.json │ │ │ ├── el-icon-bell.json │ │ │ ├── el-icon-s-comment.json │ │ │ ├── el-icon-s-opportunity.json │ │ │ ├── el-icon-d-arrow-left.json │ │ │ ├── el-icon-female.json │ │ │ ├── el-icon-share.json │ │ │ ├── el-icon-video-pause.json │ │ │ ├── el-icon-message-solid.json │ │ │ ├── el-icon-switch-button.json │ │ │ ├── el-icon-remove-outline.json │ │ │ ├── el-icon-chat-round.json │ │ │ ├── el-icon-error.json │ │ │ ├── el-icon-d-arrow-right.json │ │ │ ├── el-icon-warning.json │ │ │ ├── el-icon-chat-line-square.json │ │ │ ├── el-icon-folder-s.json │ │ │ ├── el-icon-message.json │ │ │ ├── el-icon-circle-plus.json │ │ │ ├── el-icon-s-tools.json │ │ │ ├── el-icon-picture-outline.json │ │ │ ├── el-icon-picture.json │ │ │ ├── el-icon-time.json │ │ │ ├── el-icon-sort.json │ │ │ ├── el-icon-circle-check.json │ │ │ ├── el-icon-location-outline.json │ │ │ ├── el-icon-location.json │ │ │ ├── el-icon-check.json │ │ │ ├── el-icon-male.json │ │ │ ├── el-icon-cloudy.json │ │ │ ├── el-icon-full-screen.json │ │ │ ├── el-icon-link.json │ │ │ ├── el-icon-video-play.json │ │ │ ├── el-icon-circle-plus-outline.json │ │ │ ├── el-icon-coffee-cup.json │ │ │ ├── el-icon-delete-solid.json │ │ │ ├── el-icon-edit-outline.json │ │ │ ├── el-icon-refresh-right.json │ │ │ ├── el-icon-warning-outline.json │ │ │ ├── el-icon-delete.json │ │ │ ├── el-icon-location-information.json │ │ │ ├── el-icon-zoom-out.json │ │ │ ├── el-icon-lock.json │ │ │ ├── el-icon-menu.json │ │ │ ├── el-icon-question.json │ │ │ ├── el-icon-brush.json │ │ │ ├── el-icon-paperclip.json │ │ │ ├── el-icon-chat-line-round.json │ │ │ ├── el-icon-rotate-left.json │ │ │ ├── el-icon-rotate-right.json │ │ │ ├── el-icon-unlock.json │ │ │ ├── el-icon-camera.json │ │ │ ├── el-icon-camera-solid.json │ │ │ ├── el-icon-connection.json │ │ │ ├── el-icon-circle-close.json │ │ │ ├── el-icon-info.json │ │ │ ├── el-icon-microphone.json │ │ │ ├── el-icon-zoom-in.json │ │ │ ├── el-icon-chat-dot-square.json │ │ │ ├── el-icon-close-notification.json │ │ │ ├── el-icon-place.json │ │ │ ├── el-icon-first-aid-kit.json │ │ │ ├── el-icon-refresh.json │ │ │ ├── el-icon-thumb.json │ │ │ ├── el-icon-view.json │ │ │ ├── el-icon-rank.json │ │ │ ├── el-icon-alarm-clock.json │ │ │ ├── el-icon-debug.json │ │ │ ├── el-icon-chat-dot-round.json │ │ │ ├── el-icon-turn-off-microphone.json │ │ │ ├── el-icon-undo.json │ │ │ ├── el-icon-redo.json │ │ │ ├── el-icon-date.json │ │ │ ├── el-icon-setting.json │ │ │ ├── el-icon-code.json │ │ │ └── el-icon-star-off.json │ │ └── icon.scss │ ├── PlItem │ │ ├── index.ts │ │ └── item.tsx │ ├── PlList │ │ ├── index.ts │ │ └── list.tsx │ ├── $$image │ │ └── index.ts │ ├── $$dialog │ │ └── index.ts │ ├── Plc │ │ └── index.tsx │ ├── createUseTableOption │ │ ├── utils │ │ │ ├── TableProFilter.tsx │ │ │ └── cloneTableNode.tsx │ │ └── use │ │ │ ├── setting │ │ │ ├── use.setting.config.scss │ │ │ ├── use.setting.filter.senior.scss │ │ │ ├── use.setting.utils.tsx │ │ │ └── use.setting.filter.all.scss │ │ │ ├── use.permit.tsx │ │ │ ├── filter │ │ │ └── distinct.filter.scss │ │ │ └── use.cache.utils.tsx │ ├── PlcPick │ │ └── index.tsx │ ├── $$contextmenu │ │ └── index.ts │ ├── PlRoot │ │ ├── index.ts │ │ ├── PlRoot.scss │ │ └── createDefaultService.tsx │ ├── PlColorButton │ │ ├── opacity.png │ │ ├── color-button.scss │ │ └── index.tsx │ ├── PlcDate │ │ └── index.ts │ ├── PlcGroup │ │ └── index.tsx │ ├── PlcRate │ │ └── index.ts │ ├── PlcInput │ │ └── index.ts │ ├── PlcCheck │ │ └── index.ts │ ├── PlcIndex │ │ └── index.ts │ ├── PlcNumber │ │ └── index.ts │ ├── PlcSelect │ │ └── index.ts │ ├── PlcToggle │ │ └── index.ts │ ├── PlcTree │ │ └── index.ts │ ├── PlcExpand │ │ └── index.ts │ ├── PlcCheckbox │ │ └── index.ts │ ├── PlTab │ │ └── tab.scss │ ├── PlcColorPicker │ │ └── index.ts │ ├── PlcDraggier │ │ └── index.ts │ ├── PlLoading │ │ └── loading.scss │ ├── PlEmpty │ │ ├── empty.scss │ │ └── index.tsx │ ├── useHttp │ │ ├── index.tsx │ │ └── useHttp.utils.tsx │ ├── PlFilter │ │ ├── filter.scss │ │ └── editor │ │ │ └── FilterTextContains.tsx │ ├── $$message │ │ └── index.ts │ ├── $$notice │ │ └── index.tsx │ ├── $$loading │ │ └── index.ts │ ├── PlCascadePanel │ │ ├── cascade-service.scss │ │ └── useCascade.tsx │ ├── useTableOption │ │ └── index.tsx │ ├── useObjectOption │ │ └── index.tsx │ ├── PlTable │ │ ├── plc │ │ │ ├── format │ │ │ │ ├── process │ │ │ │ │ ├── getPltCellClass.ts │ │ │ │ │ └── copyPlcList.ts │ │ │ │ └── utils │ │ │ │ │ └── runOnce.tsx │ │ │ ├── utils │ │ │ │ ├── renderColgroup.tsx │ │ │ │ └── plc.scope-slots.tsx │ │ │ ├── core │ │ │ │ └── Plc.tsx │ │ │ ├── edit │ │ │ │ ├── plc-input.tsx │ │ │ │ ├── plc-number.tsx │ │ │ │ ├── plc-rate.tsx │ │ │ │ └── plc-color-picker.tsx │ │ │ └── standard │ │ │ │ ├── draggier │ │ │ │ └── core │ │ │ │ │ ├── utils.ts │ │ │ │ │ └── index.tsx │ │ │ │ └── plc-index.tsx │ │ └── table │ │ │ └── use │ │ │ ├── useTableGetScroll.tsx │ │ │ └── useBindScroll.ts │ ├── PlTriangle │ │ └── triangle.scss │ ├── useLoading │ │ ├── index.tsx │ │ └── full │ │ │ └── index.tsx │ ├── PlCascade │ │ └── cascade.scss │ ├── PlRadioInner │ │ ├── radio-inner.scss │ │ └── index.tsx │ ├── PlTree │ │ └── utils │ │ │ ├── tree-constant.ts │ │ │ ├── tree.utils.ts │ │ │ └── type.ts │ ├── PlTabs │ │ ├── header │ │ │ ├── horizontal │ │ │ │ ├── TabsHeaderHorizontalCard.tsx │ │ │ │ ├── TabsHeaderHorizontalShadow.tsx │ │ │ │ └── tabs-header-text.scss │ │ │ └── vertical │ │ │ │ └── TabsHeaderVertical.tsx │ │ ├── tabs.utils.tsx │ │ └── tabs.scss │ ├── PlProgressMini │ │ └── progress-mini.scss │ ├── PlForm │ │ ├── form.utils.tsx │ │ └── async.validator.utils.ts │ ├── useContextmenu │ │ └── contextmenu-service.scss │ ├── useColorPicker │ │ └── index.tsx │ ├── PlColorPicker │ │ ├── sub │ │ │ ├── color-hue-slider.scss │ │ │ ├── color-alpha-slider.scss │ │ │ └── color-sv-panel.scss │ │ ├── color-picker.scss │ │ └── color-panel.scss │ ├── PlProgressBar │ │ ├── progress.utils.ts │ │ └── progress-bar.scss │ ├── PlInputGroup │ │ ├── index.tsx │ │ └── input-group.scss │ ├── PlVirtualList │ │ └── virtual-list.scss │ ├── PlRate │ │ └── rate.scss │ ├── PlCollapse │ │ └── collapse.scss │ ├── PlTablePro │ │ └── table-pro.scss │ ├── PlTagInput │ │ └── tag-input.scss │ ├── PlDate │ │ └── useDate.tsx │ ├── PlSelect │ │ └── useSelect.tsx │ ├── PlTooltip │ │ └── tooltip.scss │ ├── PlDropdownMenu │ │ └── index.tsx │ ├── PlPopper │ │ └── refershPopperReference.tsx │ ├── initialize │ │ └── index.tsx │ ├── PlLoadingMask │ │ └── loading-mask.scss │ ├── useDialog │ │ └── dialog-service.scss │ ├── PlProgressCircle │ │ └── progress-circle.scss │ ├── PlcTextarea │ │ └── PlTextareaDialog.tsx │ ├── PlDropdownGroup │ │ └── index.tsx │ ├── PlcObject │ │ └── index.tsx │ ├── PlBadge │ │ └── badge.scss │ ├── PlCheckboxInner │ │ └── index.tsx │ └── useEditPopperAgent │ │ └── useEditPopperAgent.utils.tsx ├── utils │ ├── type.ts │ ├── getScrollParent.ts │ ├── getElement.ts │ ├── ifSlotIsString.tsx │ ├── createError.ts │ ├── getRowEl.ts │ ├── createKeyHandler.ts │ ├── constant.tsx │ ├── ClickBodyListener.tsx │ ├── createFlagManager.ts │ ├── createAnimate.ts │ └── findReactElement.tsx ├── styles │ ├── global-import.scss │ ├── theme │ │ └── blue.scss │ └── public │ │ └── public.scss ├── index.ts └── use │ └── useFunctionWrapper.ts ├── .eslintignore ├── public ├── favicon.ico └── index.html ├── babel.config.js ├── shims-vue.d.ts ├── .gitignore ├── README.md ├── tsconfig.json └── .eslintrc.js /story/env/index.ts: -------------------------------------------------------------------------------- 1 | export const env = APP_ENV -------------------------------------------------------------------------------- /story/env/config/undefined.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /src/packages/PlTime/panel/time.public.scss: -------------------------------------------------------------------------------- 1 | $time-size: 24px; -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist/ 3 | test 4 | build/ 5 | src/libs -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plain-pot/plain-ui/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-caret-top.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlItem/index.ts: -------------------------------------------------------------------------------- 1 | import {PlItem} from './item' 2 | 3 | export default PlItem 4 | -------------------------------------------------------------------------------- /src/packages/PlList/index.ts: -------------------------------------------------------------------------------- 1 | import {PlList} from './list' 2 | 3 | export default PlList 4 | -------------------------------------------------------------------------------- /story/env/config/local.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | base: 'http://localhost:7001', 3 | } 4 | -------------------------------------------------------------------------------- /story/env/config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | base: 'http://1.116.13.72:7001', 3 | } -------------------------------------------------------------------------------- /story/pages/test/TestGroupTransition.scss: -------------------------------------------------------------------------------- 1 | .demo-btn:active { 2 | color: blue; 3 | } 4 | -------------------------------------------------------------------------------- /src/packages/$$image/index.ts: -------------------------------------------------------------------------------- 1 | import {$$image} from "../useImage"; 2 | 3 | export default $$image -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-caret-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/env/env.d.ts: -------------------------------------------------------------------------------- 1 | declare const APP_ENV: { 2 | base: string, 3 | secret_key: string, 4 | } -------------------------------------------------------------------------------- /src/packages/$$dialog/index.ts: -------------------------------------------------------------------------------- 1 | import {$$dialog} from "../useDialog"; 2 | 3 | export default $$dialog -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-caret-left.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-caret-bottom.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/Plc/index.tsx: -------------------------------------------------------------------------------- 1 | import Plc from '../PlTable/plc/core/Plc' 2 | 3 | export {Plc} 4 | export default Plc -------------------------------------------------------------------------------- /src/packages/createUseTableOption/utils/TableProFilter.tsx: -------------------------------------------------------------------------------- 1 | export const TableProFilter = (() => { 2 | 3 | })(); -------------------------------------------------------------------------------- /src/packages/PlcPick/index.tsx: -------------------------------------------------------------------------------- 1 | import PlcCheck from '../PlTable/plc/standard/plc-pick' 2 | 3 | export default PlcCheck -------------------------------------------------------------------------------- /src/packages/$$contextmenu/index.ts: -------------------------------------------------------------------------------- 1 | import {$$contextmenu} from "../useContextmenu"; 2 | 3 | export default $$contextmenu -------------------------------------------------------------------------------- /story/pages/normal/DemoDialog.scss: -------------------------------------------------------------------------------- 1 | .demo-dialog { 2 | .pl-dialog-content { 3 | color: #12b4a5; 4 | } 5 | } -------------------------------------------------------------------------------- /src/packages/PlRoot/index.ts: -------------------------------------------------------------------------------- 1 | import {PlRoot} from "./PlRoot"; 2 | 3 | export { 4 | PlRoot 5 | } 6 | export default PlRoot -------------------------------------------------------------------------------- /src/packages/PlColorButton/opacity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plain-pot/plain-ui/HEAD/src/packages/PlColorButton/opacity.png -------------------------------------------------------------------------------- /src/packages/PlcDate/index.ts: -------------------------------------------------------------------------------- 1 | import PlcDate from '../PlTable/plc/edit/plc-date' 2 | 3 | export {PlcDate} 4 | 5 | export default PlcDate -------------------------------------------------------------------------------- /src/packages/PlcGroup/index.tsx: -------------------------------------------------------------------------------- 1 | import PlcGroup from "../PlTable/plc/core/PlcGroup"; 2 | 3 | export {PlcGroup} 4 | export default PlcGroup -------------------------------------------------------------------------------- /src/packages/PlcRate/index.ts: -------------------------------------------------------------------------------- 1 | import PlcRate from '../PlTable/plc/edit/plc-rate' 2 | 3 | export {PlcRate} 4 | 5 | export default PlcRate -------------------------------------------------------------------------------- /src/packages/PlcInput/index.ts: -------------------------------------------------------------------------------- 1 | import PlcInput from '../PlTable/plc/edit/plc-input' 2 | 3 | export {PlcInput} 4 | 5 | export default PlcInput -------------------------------------------------------------------------------- /src/packages/PlcCheck/index.ts: -------------------------------------------------------------------------------- 1 | import PlcCheck from '../PlTable/plc/standard/plc-check' 2 | 3 | export {PlcCheck} 4 | 5 | export default PlcCheck -------------------------------------------------------------------------------- /src/packages/PlcIndex/index.ts: -------------------------------------------------------------------------------- 1 | import PlcIndex from '../PlTable/plc/standard/plc-index' 2 | 3 | export {PlcIndex} 4 | 5 | export default PlcIndex -------------------------------------------------------------------------------- /src/packages/PlcNumber/index.ts: -------------------------------------------------------------------------------- 1 | import PlcNumber from '../PlTable/plc/edit/plc-number' 2 | 3 | export {PlcNumber} 4 | 5 | export default PlcNumber -------------------------------------------------------------------------------- /src/packages/PlcSelect/index.ts: -------------------------------------------------------------------------------- 1 | import PlcSelect from '../PlTable/plc/edit/plc-select' 2 | 3 | export {PlcSelect} 4 | 5 | export default PlcSelect -------------------------------------------------------------------------------- /src/packages/PlcToggle/index.ts: -------------------------------------------------------------------------------- 1 | import PlcToggle from '../PlTable/plc/edit/plc-toggle' 2 | 3 | export {PlcToggle} 4 | 5 | export default PlcToggle -------------------------------------------------------------------------------- /src/packages/PlcTree/index.ts: -------------------------------------------------------------------------------- 1 | import PlcTree from '../PlTable/plc/standard/tree/plc-tree' 2 | 3 | export {PlcTree} 4 | 5 | export default PlcTree -------------------------------------------------------------------------------- /src/packages/PlcExpand/index.ts: -------------------------------------------------------------------------------- 1 | import PlcExpand from '../PlTable/plc/standard/plc-expand' 2 | 3 | export {PlcExpand} 4 | 5 | export default PlcExpand -------------------------------------------------------------------------------- /src/packages/PlcCheckbox/index.ts: -------------------------------------------------------------------------------- 1 | import PlcCheckbox from '../PlTable/plc/edit/plc-checkbox' 2 | 3 | export {PlcCheckbox} 4 | 5 | export default PlcCheckbox -------------------------------------------------------------------------------- /src/utils/type.ts: -------------------------------------------------------------------------------- 1 | export type RequireFormat = Required<{ [k in P]: T[k] }> & { [k in Exclude]: T[k] } 2 | 3 | export default {} -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-promotion.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTab/tab.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | /*.pl-inner-tab { 3 | transform-origin: left top; 4 | transition: all 500ms $transition; 5 | }*/ 6 | } 7 | -------------------------------------------------------------------------------- /src/packages/PlcColorPicker/index.ts: -------------------------------------------------------------------------------- 1 | import PlcColorPicker from '../PlTable/plc/edit/plc-color-picker' 2 | 3 | export {PlcColorPicker} 4 | 5 | export default PlcColorPicker -------------------------------------------------------------------------------- /src/packages/PlcDraggier/index.ts: -------------------------------------------------------------------------------- 1 | import PlcDraggier from '../PlTable/plc/standard/draggier/plc-draggier' 2 | 3 | export {PlcDraggier} 4 | 5 | export default PlcDraggier -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-fold.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-unfold.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlLoading/loading.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-loading { 3 | @include statusMixin(loading) { 4 | color: $value; 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-order.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-minus.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | declare module '*.vue' { 3 | import type { DefineComponent } from 'vue' 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /src/packages/PlEmpty/empty.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-empty { 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | justify-content: center; 7 | color: $icc; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /story/pages/table-pro/table-image.tsx: -------------------------------------------------------------------------------- 1 | import {designPage} from "plain-ui-composition"; 2 | 3 | 4 | export const demo1 = designPage(() => { 5 | return () => ( 6 |
7 | 8 |
9 | ) 10 | }) 11 | -------------------------------------------------------------------------------- /src/packages/useHttp/index.tsx: -------------------------------------------------------------------------------- 1 | import {iUseHttp} from "./useHttp.utils"; 2 | import {getInitialConfigState} from "../initialize"; 3 | 4 | export const useHttp: iUseHttp = () => getInitialConfigState("useHttp")() 5 | 6 | export default useHttp -------------------------------------------------------------------------------- /src/packages/PlFilter/filter.scss: -------------------------------------------------------------------------------- 1 | .pl-filter { 2 | &.pl-input-group-block { 3 | & > *:not(.pl-filter-ele) { 4 | flex: 1; 5 | 6 | & > .pl-input-inner { 7 | width: 100%; 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-jiahao.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/$$message/index.ts: -------------------------------------------------------------------------------- 1 | import {createServiceWithoutContext} from "../PlRoot/registryRootService"; 2 | import useMessage from "../useMessage"; 3 | 4 | export const $$message = createServiceWithoutContext(useMessage) 5 | 6 | export default $$message -------------------------------------------------------------------------------- /src/packages/$$notice/index.tsx: -------------------------------------------------------------------------------- 1 | import {createServiceWithoutContext} from "../PlRoot/registryRootService"; 2 | import {useNotice} from "../useNotice"; 3 | 4 | export const $$notice = createServiceWithoutContext(useNotice) 5 | 6 | export default $$notice -------------------------------------------------------------------------------- /src/packages/createUseTableOption/use/setting/use.setting.config.scss: -------------------------------------------------------------------------------- 1 | .pl-table-pro-setting-config { 2 | .pl-table-pro-setting-config-button { 3 | margin-bottom: 16px; 4 | 5 | & > * { 6 | margin-right: 8px; 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/packages/$$loading/index.ts: -------------------------------------------------------------------------------- 1 | import {$$loadingBar} from "../useLoading/bar"; 2 | import {$$loadingMask} from "../useLoading/full"; 3 | 4 | export const $$loading = { 5 | bar: $$loadingBar, 6 | full: $$loadingMask, 7 | } 8 | 9 | export default $$loading -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-list.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-folder.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/createUseTableOption/utils/cloneTableNode.tsx: -------------------------------------------------------------------------------- 1 | import {TableNode} from "../../PlTable/table/use/useTableNode"; 2 | import {deepcopy} from "plain-utils/object/deepcopy"; 3 | 4 | export function cloneTableNode(node: TableNode) { 5 | return deepcopy(node) 6 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-check-bold.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-arrow-down.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-edit.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/components/index.ts: -------------------------------------------------------------------------------- 1 | import {App} from "vue"; 2 | import {DemoLine} from "./DemoLine"; 3 | import {DemoRow} from "./DemoRow"; 4 | 5 | export const installDemoComponent = (app: App) => { 6 | app.component('demo-line', DemoLine) 7 | app.component('demo-row', DemoRow) 8 | } 9 | -------------------------------------------------------------------------------- /src/packages/PlCascadePanel/cascade-service.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | [service-name=pl-popper-service-cascade] { 3 | .pl-popper-content-inner { 4 | padding: 0 !important; 5 | } 6 | 7 | .pl-cascade-panel { 8 | border: none !important; 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-arrow-left.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-document-remove.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-upload1.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/useTableOption/index.tsx: -------------------------------------------------------------------------------- 1 | import {tUseTableOption} from "../createUseTableOption"; 2 | import {getInitialConfigState} from "../initialize"; 3 | 4 | const useTableOption: tUseTableOption = (config) => getInitialConfigState('useTableOption')(config) 5 | 6 | export default useTableOption -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-folder-remove.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-grid.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-ticket.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/useObjectOption/index.tsx: -------------------------------------------------------------------------------- 1 | import {tUseTableOption} from "../createUseTableOption"; 2 | import {getInitialConfigState} from "../initialize"; 3 | 4 | const useObjectOption: tUseTableOption = (config) => getInitialConfigState('useObjectOption')(config) 5 | 6 | export default useObjectOption -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-arrow-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-download.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTable/plc/format/process/getPltCellClass.ts: -------------------------------------------------------------------------------- 1 | import {tPlcType} from "../../utils/plc.type"; 2 | 3 | export function getPltCellClass(plc: tPlcType) { 4 | return { 5 | // 'pl-cell-group': plc.group, 6 | [`plt-cell-align-${plc.props.align}`]: !!plc.props.align, 7 | } 8 | } -------------------------------------------------------------------------------- /src/packages/PlTable/plc/format/utils/runOnce.tsx: -------------------------------------------------------------------------------- 1 | export function runOnce void>(run: Run): Run { 2 | let done = false 3 | return ((...args: any[]) => { 4 | if (!done) { 5 | run(...args) 6 | done = true 7 | } 8 | }) as any 9 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-plus.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-custom.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTime/panel/time-range-panel.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-time-range-panel { 3 | display: inline-block; 4 | 5 | .pl-time-base-panel { 6 | 7 | &:first-child { 8 | border-right: solid 1px $ibc; 9 | border-radius: 0; 10 | } 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-document-add.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/styles/global-import.scss: -------------------------------------------------------------------------------- 1 | @import "./main"; 2 | @import "./theme/blue"; 3 | 4 | $themes: map_merge($theme-default, $theme-blue); 5 | 6 | @mixin theme { 7 | @each $curThemeName, $curTheme in $themes { 8 | @include generateThemeContent($curThemeName, $curTheme) { 9 | @content; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-folder-add.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/utils/getScrollParent.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 获取可以滚动的父组件 3 | * @author 韦胜健 4 | * @date 2020/8/19 23:50 5 | */ 6 | export function getScrollParent(el: HTMLElement): HTMLElement { 7 | while (!!el && el.scrollHeight <= el.offsetHeight) { 8 | el = el.parentNode as HTMLElement 9 | } 10 | return el 11 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-arrow-up.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-document.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTriangle/triangle.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-triangle { 3 | display: inline-block; 4 | vertical-align: middle; 5 | overflow: hidden; 6 | box-sizing: border-box; 7 | 8 | .pl-triangle-target { 9 | width: 0; 10 | height: 0; 11 | position: relative; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/packages/PlTable/plc/utils/renderColgroup.tsx: -------------------------------------------------------------------------------- 1 | 2 | import {tPlc} from "./plc.type"; 3 | 4 | export function renderColgroup(flatPlcList: tPlc[]) { 5 | return ( 6 | 7 | {flatPlcList.map((plc, index) => )} 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-top.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/useLoading/index.tsx: -------------------------------------------------------------------------------- 1 | import {useLoadingMask} from "./full"; 2 | import {useLoadingBar} from "./bar"; 3 | 4 | export function useLoading() { 5 | const mask = useLoadingMask() 6 | const bar = useLoadingBar() 7 | return { 8 | full: mask, 9 | bar: bar, 10 | } 11 | } 12 | 13 | export default useLoading -------------------------------------------------------------------------------- /story/main.tsx: -------------------------------------------------------------------------------- 1 | import {createApp} from 'vue' 2 | import PlainUi from '../src' 3 | console.log(PlainUi) 4 | import './init/index' 5 | import App from './App' 6 | import {installDemoComponent} from "./components"; 7 | 8 | const app = createApp(App) 9 | app.use(PlainUi) 10 | app.use({install: installDemoComponent}) 11 | app.mount('#app') 12 | -------------------------------------------------------------------------------- /story/pages/test/TestGroupTransition.tsx: -------------------------------------------------------------------------------- 1 | import './TestGroupTransition.scss' 2 | import {designPage} from "plain-ui-composition"; 3 | 4 | export const demo1 = designPage(() => { 5 | return () => ( 6 |
7 | this is button, this is hello world 8 |
9 | ) 10 | }) 11 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-bottom.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-position.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-star-on.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-document-checked.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-bottom-left.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-top-left.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-upload.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-bottom-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-collection-tag.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-folder-checked.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-remove.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlCascade/cascade.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-cascade { 3 | .pl-input-suffix-icon .pl-icon { 4 | transform: rotate(90deg); 5 | transition: transform 300ms $transition; 6 | } 7 | 8 | &.pl-cascade-open { 9 | .pl-input-suffix-icon .pl-icon { 10 | transform: rotate(-90deg); 11 | } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-back.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-shop.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-top-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-crop.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTime/panel/time-panel.utils.ts: -------------------------------------------------------------------------------- 1 | export const TimePublicProps = { 2 | displayFormat: {type: String, default: 'HH:mm:ss'}, 3 | valueFormat: {type: String, default: 'HH:mm:ss'}, 4 | max: {type: String}, 5 | min: {type: String}, 6 | layout: {type: Array, default: () => (['h', 'm', 's'])}, 7 | custom: Function, 8 | checkDisabled: Function, 9 | } -------------------------------------------------------------------------------- /src/utils/getElement.ts: -------------------------------------------------------------------------------- 1 | export function getElement(ref: any): HTMLElement | null { 2 | 3 | if (!ref) { 4 | return null 5 | } 6 | 7 | if (!!ref.$el) { 8 | return getElement(ref.$el) 9 | } 10 | 11 | if (ref.nodeType !== 3) { 12 | return ref 13 | } 14 | 15 | return !!ref.data ? ref : ref.nextElementSibling 16 | 17 | } -------------------------------------------------------------------------------- /src/utils/ifSlotIsString.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * is slot is string 3 | * @author 韦胜健 4 | * @date 2021/3/18 17:56 5 | */ 6 | export function isis(slotFunc: () => any, renderString: (str: string) => any, defaultSlot?: any) { 7 | const slot = slotFunc() 8 | if (slot == null) return defaultSlot 9 | return typeof slot === "string" ? renderString(slot) : slot 10 | } -------------------------------------------------------------------------------- /story/pages/normal/DemoStep.scss: -------------------------------------------------------------------------------- 1 | .demo-step { 2 | width: 1060px; 3 | 4 | .demo-line { 5 | display: flex; 6 | 7 | .demo-line-content { 8 | flex: 1; 9 | } 10 | } 11 | 12 | .custom-content-slot { 13 | .pl-icon { 14 | margin-right: 6px; 15 | font-size: 1.2em; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/packages/PlRadioInner/radio-inner.scss: -------------------------------------------------------------------------------- 1 | .pl-radio-inner { 2 | 3 | width: 1.1em; 4 | height: 1.1em; 5 | 6 | display: inline-block; 7 | box-sizing: border-box; 8 | border-color: currentColor; 9 | border-width: 1px; 10 | border-style: solid; 11 | border-radius: 100px; 12 | 13 | circle { 14 | fill: currentColor; 15 | stroke: currentColor; 16 | } 17 | } -------------------------------------------------------------------------------- /src/packages/PlTree/utils/tree-constant.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 拖拽放置的类型 3 | * @author 韦胜健 4 | * @date 2020/4/1 17:15 5 | */ 6 | export enum TreeDropType { 7 | prev = 'prev', 8 | inner = 'inner', 9 | next = 'next', 10 | null = 'null', 11 | } 12 | 13 | export enum TreeNodeCheckStatus { 14 | check = 'check', 15 | uncheck = 'uncheck', 16 | minus = 'minus', 17 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | #/dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | 25 | yarn.lock 26 | package-lock.json 27 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-close.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-search.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-chat-square.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTime/useTime.tsx: -------------------------------------------------------------------------------- 1 | import {createUseEditPopperAgent} from "../useEditPopperAgent/createAgentGetter"; 2 | import {PlTimePanel} from "./panel/PlTimePanel"; 3 | 4 | export const useTime = createUseEditPopperAgent({ 5 | name: 'time', 6 | render: (attrs) => , 7 | defaultPopperAttrs: { 8 | transition: 'pl-transition-popper-drop', 9 | }, 10 | }) 11 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-document-copy.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-folder-opened.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlRoot/PlRoot.scss: -------------------------------------------------------------------------------- 1 | @import "../../styles/public/public"; 2 | 3 | .pl-root-service-container { 4 | position: fixed; 5 | width: 100vw; 6 | height: 100vh; 7 | overflow: hidden; 8 | //background-color: rgba(black, 0.1); 9 | top: 0; 10 | left: 0; 11 | pointer-events: none; 12 | z-index: 1500; 13 | 14 | & > * { 15 | pointer-events: auto; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-more.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import {App} from 'vue' 2 | import * as all from './entry' 3 | 4 | const install = (app: App) => { 5 | Object.entries(all).forEach(([key, item]) => { 6 | if ('install' in item) { 7 | // console.log('install key', key) 8 | app.use(item as any) 9 | } 10 | }) 11 | } 12 | 13 | export {install} 14 | export * from './entry' 15 | 16 | export default {...all, install} 17 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-document-delete.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-folder-delete.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-success.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # plain-ui-new 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-delete-location.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-bell.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/utils/createError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 创建一个报错对象 3 | * @author 韦胜健 4 | * @date 2020/10/15 10:33 5 | */ 6 | export function createError(tag: string) { 7 | return (msg: string, isLog?: boolean) => { 8 | const message = `${tag}:${msg}` 9 | const log = isLog == null ? true : isLog 10 | if (log) { 11 | console.error(message) 12 | } else { 13 | throw new Error(message) 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-comment.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-opportunity.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-d-arrow-left.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-female.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/pages/table/DemoTableClassAndStyle.scss: -------------------------------------------------------------------------------- 1 | .custom-row { 2 | &.custom-row-status-active { 3 | td { 4 | background-color: rgba(#3E97EC, 0.1) !important; 5 | } 6 | } 7 | } 8 | 9 | .custom-cell { 10 | &.custom-cell-status-active { 11 | background-color: rgba(#3E97EC, 0.1) !important; 12 | } 13 | } 14 | 15 | .custom-head-cell-clz { 16 | background-color: #3E97EC !important; 17 | color: white !important; 18 | } -------------------------------------------------------------------------------- /src/packages/PlTable/table/use/useTableGetScroll.tsx: -------------------------------------------------------------------------------- 1 | import {PlainScroll} from "../../../PlScroll"; 2 | 3 | export function useTableGetScroll(onVirtualMounted: (cb: (data: { scroll: PlainScroll }) => void) => void, onChange?: (scroll: PlainScroll) => void) { 4 | let val: PlainScroll 5 | onVirtualMounted(({scroll}) => { 6 | val = scroll; 7 | !!onChange && onChange(scroll) 8 | }) 9 | return { 10 | getScroll: () => val! 11 | } 12 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-share.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icon.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-icon { 3 | 4 | display: inline-block; 5 | height: 1em; 6 | width: 1em; 7 | line-height: normal; 8 | 9 | &.el-svg-icon { 10 | vertical-align: -0.15em; 11 | 12 | path { 13 | fill: currentColor; 14 | } 15 | } 16 | 17 | @include statusMixin(icon) { 18 | color: $value; 19 | } 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-video-pause.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-message-solid.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-switch-button.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-remove-outline.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/pages/normal/DemoList.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .demo-list { 3 | .test-item { 4 | position: relative; 5 | height: 120px; 6 | width: 200px; 7 | margin-bottom: 12px; 8 | margin-right: 12px; 9 | border-radius: 8px; 10 | padding: 12px; 11 | color: white; 12 | background-color: $colorPrimary; 13 | display: inline-block !important; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-chat-round.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-error.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTabs/header/horizontal/TabsHeaderHorizontalCard.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition"; 2 | import {TabCommonProps} from "../../tabs.utils"; 3 | import './tabs-header-card.scss' 4 | 5 | export const PlTabsHeaderHorizontalCard = designComponent({ 6 | props: { 7 | ...TabCommonProps, 8 | }, 9 | slots: ['default'], 10 | setup({props, slots}) { 11 | return () => <> 12 | {slots.default()} 13 | 14 | }, 15 | }) 16 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-d-arrow-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-warning.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlProgressMini/progress-mini.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-progress-mini { 3 | vertical-align: middle; 4 | display: inline-flex; 5 | align-items: center; 6 | justify-content: center; 7 | overflow: hidden; 8 | 9 | svg { 10 | flex-shrink: 0; 11 | width: 200%; 12 | height: 200%; 13 | } 14 | 15 | &.pl-progress-mini-round { 16 | border-radius: 1000px; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/packages/PlTabs/header/horizontal/TabsHeaderHorizontalShadow.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition"; 2 | import {TabCommonProps} from "../../tabs.utils"; 3 | import './tabs-header-shadow.scss' 4 | 5 | export const PlTabsHeaderHorizontalShadow = designComponent({ 6 | props: { 7 | ...TabCommonProps, 8 | }, 9 | slots: ['default'], 10 | setup({props, slots}) { 11 | return () => <> 12 | {slots.default()} 13 | 14 | }, 15 | }) 16 | -------------------------------------------------------------------------------- /story/init/useObjectOption.tsx: -------------------------------------------------------------------------------- 1 | import useTableOption from "./useTableOption"; 2 | 3 | const useObjectOption: typeof useTableOption = (config) => { 4 | 5 | if (config.enable == null) { 6 | config.enable = false 7 | } 8 | 9 | config.fill = undefined 10 | if (config.showRows == null) { 11 | config.showRows = Math.ceil((document.body.offsetHeight * 0.8 - 200) / 48) - 1 12 | } 13 | 14 | return useTableOption(config) 15 | } 16 | 17 | export default useObjectOption 18 | -------------------------------------------------------------------------------- /src/packages/PlForm/form.utils.tsx: -------------------------------------------------------------------------------- 1 | export enum FormLabelAlign { 2 | left = 'left', 3 | center = 'center', 4 | right = 'right', 5 | } 6 | 7 | export enum FormContentAlign { 8 | 'flex-start' = 'flex-start', 9 | 'flex-end' = 'flex-end', 10 | 'center' = 'center', 11 | 'space-around' = 'space-around', 12 | 'space-between' = 'space-between', 13 | 'space-evenly' = 'space-evenly', 14 | } 15 | 16 | export enum FormValidateMode { 17 | form = 'form', 18 | table = 'table', 19 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-chat-line-square.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-folder-s.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-message.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-circle-plus.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-s-tools.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/useContextmenu/contextmenu-service.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-contextmenu-service { 3 | position: fixed; 4 | 5 | .pl-contextmenu-service-body { 6 | transition: all $transition 300ms; 7 | transform-origin: top left; 8 | box-sizing: border-box; 9 | box-shadow: $boxshadow; 10 | padding: 4px 0; 11 | border: solid 1px $ibc; 12 | 13 | .pl-dropdown-option { 14 | font-size: 12px; 15 | color: $itc; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-picture-outline.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-picture.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-time.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-sort.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-circle-check.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/styles/theme/blue.scss: -------------------------------------------------------------------------------- 1 | $theme-blue: ( 2 | /*'blue':( 3 | colorPrimary: #409EFF, 4 | colorSuccess: #67C23A, 5 | colorWarn: #E6A23C, 6 | colorError: #F56C6C, 7 | colorInfo:#909399, 8 | 9 | shapeFillet:4px, 10 | ), 11 | 'violet':( 12 | colorPrimary: #8A2BE2, 13 | colorSuccess: #4caf50, 14 | colorWarn: #ff9800, 15 | colorError: #e91e63, 16 | colorInfo:#000042, 17 | 18 | shapeFillet:8px, 19 | )*/ 20 | ); -------------------------------------------------------------------------------- /src/utils/getRowEl.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 获取拖拽的rowEl对象 3 | * @author 韦胜健 4 | * @date 2020/8/19 23:55 5 | */ 6 | import {hasClass} from "plain-utils/dom/hasClass"; 7 | 8 | export function getRowEl(e: MouseEvent, rowClass: string): HTMLElement { 9 | let rowEl = e.target as HTMLElement 10 | while (!!rowEl && !hasClass(rowEl, rowClass)) { 11 | rowEl = rowEl.parentNode as HTMLElement 12 | } 13 | if (!rowEl) { 14 | console.log({e, rowClass}) 15 | throw new Error(`can't find item element!`) 16 | } 17 | return rowEl 18 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-location-outline.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-location.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/pages/normal/DemoScroll.scss: -------------------------------------------------------------------------------- 1 | .demo-scroll { 2 | .demo-scroll-wrapper { 3 | background-color: #f6f6f6; 4 | height: 198px; 5 | width: 91px; 6 | display: inline-block; 7 | } 8 | 9 | .demo-scroll-content { 10 | height: 400px; 11 | width: 400px; 12 | display: inline-block; 13 | } 14 | 15 | .demo-scroll-label { 16 | /*margin: 50px 0;*/ 17 | padding: 8px 16px; 18 | border-bottom: solid 1px white; 19 | font-size: 12px; 20 | box-sizing: border-box; 21 | } 22 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-check.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/pages/normal/DemoGrid.scss: -------------------------------------------------------------------------------- 1 | .demo-layout { 2 | .demo-row .demo-row-body > * { 3 | margin-right: 0 !important; 4 | } 5 | } 6 | 7 | @include theme { 8 | .ct-cls { 9 | background-color: #f2f2f2; 10 | height: 32px; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | border-radius: 2px; 15 | } 16 | 17 | .pl-row { 18 | .pl-col:nth-child(odd) { 19 | .ct-cls { 20 | background-color: #e2e2e2; 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-male.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/useColorPicker/index.tsx: -------------------------------------------------------------------------------- 1 | import {createUseEditPopperAgent} from "../useEditPopperAgent/createAgentGetter"; 2 | import PlColorPanel from "../PlColorPicker/PlColorPanel"; 3 | 4 | 5 | export const useColorPicker = createUseEditPopperAgent({ 6 | name: 'color-picker', 7 | render(attrs: any) { 8 | return 9 | }, 10 | defaultPopperAttrs: { 11 | transition: 'pl-transition-popper-drop', 12 | }, 13 | defaultRenderAttrs: { 14 | onChange() {this.hide()}, 15 | }, 16 | }) 17 | 18 | export default useColorPicker 19 | -------------------------------------------------------------------------------- /story/init/index.tsx: -------------------------------------------------------------------------------- 1 | import {initialize} from '../../src/packages/initialize' 2 | import useTableOption from "./useTableOption"; 3 | import useObjectOption from "./useObjectOption"; 4 | import {useHttp} from "./useHttp"; 5 | import {useAddressConfig} from "./useAddressConfig"; 6 | import {useOvConfig} from "./useOvConfig"; 7 | 8 | initialize(() => ({ 9 | useTableOption, 10 | useObjectOption, 11 | useHttp, 12 | useAddressConfig, 13 | useOvConfig, 14 | getExceljs: () => import('exceljs'), 15 | // @ts-ignore 16 | getFileSaver: () => import('file-saver'), 17 | })) 18 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-cloudy.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/utils/createKeyHandler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 创建一个用来管理key的对象 3 | * @author 韦胜健 4 | * @date 2020/11/27 11:38 5 | */ 6 | export function createKeyHandler(prefix: string) { 7 | const map = new WeakMap() 8 | let count = 1 9 | return (obj: any, keyField?: string | null): string => { 10 | if (!!keyField && obj[keyField]) { 11 | return obj[keyField] 12 | } 13 | let key = map.get(obj) 14 | if (!key) { 15 | key = `${prefix}_${count++}` 16 | map.set(obj, key) 17 | } 18 | return String(key) 19 | } 20 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-full-screen.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-link.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-video-play.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-circle-plus-outline.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-coffee-cup.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-delete-solid.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-edit-outline.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-refresh-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-warning-outline.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-delete.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-location-information.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-zoom-out.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/pages/normal/DemoRadio.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .demo-radio { 3 | .demo-radio-block { 4 | width: 120px; 5 | height: 80px; 6 | border: solid 1px $ibl; 7 | border-radius: $shapeFillet; 8 | display: inline-flex; 9 | align-items: center; 10 | justify-content: center; 11 | cursor: pointer; 12 | @include transition; 13 | } 14 | 15 | .demo-radio-block-is-active { 16 | background-color: $colorPrimaryLight; 17 | border-color: $colorPrimary; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-lock.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-menu.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-question.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-brush.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-paperclip.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/createUseTableOption/use/use.permit.tsx: -------------------------------------------------------------------------------- 1 | import {tTableOptionConfig} from "../createUseTableOption.utils"; 2 | import {tTableOptionHooks} from "./use.hooks"; 3 | import {usePermission} from "./userPermission"; 4 | 5 | export function useTableOptionPermit({config, hooks}: { config: tTableOptionConfig, hooks: tTableOptionHooks }) { 6 | const {init, permit} = usePermission({ 7 | ...config, 8 | onGetEnable: hooks.onGetEnable.exec, 9 | }) 10 | hooks.onInit.use(async () => {await init}) 11 | return permit 12 | } 13 | 14 | export type tTableOptionPermit = ReturnType 15 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-chat-line-round.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlColorPicker/sub/color-hue-slider.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-color-hue-slider { 3 | background: linear-gradient(90deg, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red); 4 | display: inline-block; 5 | height: 10px; 6 | position: relative; 7 | cursor: pointer; 8 | border-radius: 10px; 9 | 10 | .pl-color-hue-slider-thumb { 11 | display: inline-block; 12 | height: 100%; 13 | background-color: white; 14 | position: absolute; 15 | top: 0; 16 | border: solid 1px $colorInfo; 17 | box-sizing: border-box; 18 | border-radius: 100px; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-rotate-left.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-rotate-right.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-unlock.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-camera.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-camera-solid.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/App.tsx: -------------------------------------------------------------------------------- 1 | import {defineComponent} from "vue"; 2 | import {DemoRowController} from "./components/DemoRowController"; 3 | import {AppMenu} from "./app/AppMenu"; 4 | import {AppNavigator} from "./app/AppNavigator"; 5 | import './app.scss' 6 | import {PlRoot} from "../src/packages/PlRoot"; 7 | 8 | export default defineComponent(() => { 9 | return () => <> 10 | 11 | 12 |
13 |
Plain Design
14 |
15 | 16 | 17 |
18 |
19 | 20 | }) -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-connection.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlProgressBar/progress.utils.ts: -------------------------------------------------------------------------------- 1 | export const PROGRESS_DEFAULT_PROPS = { 2 | modelValue: {type: Number, default: 100}, // 进度百分比,双向绑定值 3 | outerColor: {type: String, default: '#f2f2f2'}, // 外层未激活颜色 4 | innerColor: {type: String, default: '#08979c'}, // 内层已经激活颜色 5 | speed: {type: Number, default: 3}, // 动画速度 6 | status: {type: String, default: 'normal'}, // 状态 7 | successColor: {type: String, default: '#52c41a'}, // 成功状态颜色 8 | errorColor: {type: String, default: '#cf1322'}, // 失败状态颜色 9 | } 10 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-circle-close.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlItem/item.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition"; 2 | 3 | export const PlItem = designComponent({ 4 | name: 'pl-item', 5 | props: { 6 | block: {type: Boolean}, 7 | tag: {type: String, default: 'div'}, 8 | }, 9 | slots: ['default'], 10 | setup({props, slots}) { 11 | return { 12 | render: () => { 13 | const {tag: Tag} = props as any 14 | return ( 15 | 16 | {slots.default()} 17 | 18 | ) 19 | } 20 | } 21 | }, 22 | }) 23 | -------------------------------------------------------------------------------- /src/packages/createUseTableOption/use/setting/use.setting.filter.senior.scss: -------------------------------------------------------------------------------- 1 | .pl-table-pro-setting-senior-filter { 2 | .pl-table-pro-setting-senior-filter-button { 3 | display: flex; 4 | justify-content: space-between; 5 | 6 | .pl-button + * { 7 | margin-left: 8px; 8 | } 9 | } 10 | 11 | .pl-table-pro-setting-senior-filter-item { 12 | margin-bottom: 16px; 13 | 14 | .pl-table-pro-setting-senior-filter-item-id { 15 | width: 80px; 16 | display: inline-block; 17 | text-align: center; 18 | } 19 | 20 | .pl-table-pro-setting-senior-filter-item-content { 21 | width: calc(100% - 80px); 22 | display: inline-block; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/packages/PlInputGroup/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, useClasses} from "plain-ui-composition"; 2 | import './input-group.scss' 3 | 4 | export const PlInputGroup = designComponent({ 5 | name: 'pl-input-group', 6 | props: { 7 | block: {type: Boolean} 8 | }, 9 | slots: ['default'], 10 | setup({props, slots}) { 11 | 12 | const classes = useClasses(() => [ 13 | 'pl-input-group', 14 | {'pl-input-group-block': props.block} 15 | ]) 16 | 17 | return () => ( 18 |
19 | {slots.default()} 20 |
21 | ) 22 | }, 23 | }) 24 | 25 | export default PlInputGroup 26 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-info.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-microphone.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-zoom-in.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/createUseTableOption/use/setting/use.setting.utils.tsx: -------------------------------------------------------------------------------- 1 | import {VueNode} from "plain-ui-composition"; 2 | 3 | export interface iTableOptionSettingConfig { 4 | key: eTableOptionSettingView, 5 | title: string, 6 | seq: number, 7 | render: () => VueNode, 8 | beforeOpen?: () => void | Promise, 9 | contentPending?: boolean, 10 | } 11 | 12 | export interface iTableOptionSettingInnerUser { 13 | (config: iTableOptionSettingConfig): void 14 | } 15 | 16 | export enum eTableOptionSettingView { 17 | seniorFilter = 'seniorFilter', 18 | allFilter = 'allFilter', 19 | sort = 'sort', 20 | config = 'config', 21 | cache = 'cache', 22 | import = 'import', 23 | export = 'export', 24 | } 25 | -------------------------------------------------------------------------------- /story/components/DemoLine.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition" 2 | 3 | export const DemoLine = designComponent({ 4 | name: 'demo-line', 5 | props: { 6 | title: {type: String}, 7 | labelWidth: {type: String}, 8 | }, 9 | slots: ['default'], 10 | setup({props, slots}) { 11 | 12 | return { 13 | render: () => ( 14 |
15 | {!!props.title &&
{props.title}
} 16 |
17 | {slots.default()} 18 |
19 |
20 | ) 21 | } 22 | }, 23 | }) 24 | -------------------------------------------------------------------------------- /src/packages/PlVirtualList/virtual-list.scss: -------------------------------------------------------------------------------- 1 | 2 | .pl-virtual-table { 3 | & > .pl-virtual-list { 4 | & > .pl-scroll-wrapper { 5 | & > .pl-scroll-content { 6 | overflow-y: unset; 7 | } 8 | } 9 | } 10 | } 11 | 12 | .pl-virtual-list { 13 | position: relative; 14 | 15 | & > .pl-scroll-wrapper { 16 | & > .pl-scroll-content { 17 | overflow-y: hidden; 18 | } 19 | } 20 | 21 | &:not(.pl-virtual-list-disabled) { 22 | .pl-virtual-list-strut { 23 | position: relative; 24 | //overflow: hidden; 25 | 26 | .pl-virtual-list-content { 27 | position: absolute; 28 | top: 0; 29 | left: 0; 30 | right: 0; 31 | //overflow: hidden; 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/packages/PlColorButton/color-button.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-color-button { 3 | border-radius: 2px; 4 | height: 24px; 5 | width: 24px; 6 | border: solid 1px $ibc; 7 | padding: 2px; 8 | box-sizing: border-box; 9 | display: inline-block; 10 | cursor: pointer; 11 | vertical-align: middle; 12 | 13 | .pl-color-button-background { 14 | background-size: 7px 7px; 15 | border-radius: 2px; 16 | box-sizing: border-box; 17 | height: 100%; 18 | width: 100%; 19 | 20 | .pl-color-button-color { 21 | height: 100%; 22 | width: 100%; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-chat-dot-square.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/useHttp/useHttp.utils.tsx: -------------------------------------------------------------------------------- 1 | export type iHttpRequestConfig = { 2 | url: string, 3 | method: any, 4 | query?: any 5 | body?: any 6 | headers?: any 7 | } & Record 8 | 9 | export type tHttpRequest = (config: iHttpRequestConfig) => Promise 10 | 11 | export type tHttp = tHttpRequest & { 12 | get: (url: string, query?: any, config?: iHttpRequestConfig) => Promise, 13 | post: (url: string, body?: any, config?: iHttpRequestConfig) => Promise, 14 | put: (url: string, body?: any, config?: iHttpRequestConfig) => Promise, 15 | delete: (url: string, body?: any, config?: iHttpRequestConfig) => Promise, 16 | } 17 | 18 | export interface iUseHttp { 19 | (): tHttp 20 | } -------------------------------------------------------------------------------- /story/init/useHttp.tsx: -------------------------------------------------------------------------------- 1 | import {iUseHttp, tHttp, tHttpRequest} from "../../src/packages/useHttp/useHttp.utils"; 2 | import {$http} from "../http/http"; 3 | 4 | const request: tHttpRequest = (config) => { 5 | return $http(config) 6 | } 7 | 8 | const http: tHttp = Object.assign(request, { 9 | get: (url: string, query: any, config: any) => $http.get(url, { 10 | ...(config || {}), 11 | params: query, 12 | }) as any, 13 | post: (url: string, body: any, config: any) => $http.post(url, body, config) as any, 14 | put: (url: string, body: any, config: any) => $http.post(url, body, config) as any, 15 | delete: (url: string, body: any, config: any) => $http.post(url, body, config) as any, 16 | }) 17 | 18 | export const useHttp: iUseHttp = () => http -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-close-notification.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTable/plc/core/Plc.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition"; 2 | import {PlcEmitsOptions, PlcPropsOptions} from "../utils/plc.utils"; 3 | 4 | import {PlcScopeSlotsOptions} from "../utils/plc.scope-slots"; 5 | import {useBasePlc} from "./useBasePlc"; 6 | import {applyPropsState, getPropsState} from "../utils/usePropsState"; 7 | 8 | export const Plc = designComponent({ 9 | name: 'plc', 10 | props: PlcPropsOptions, 11 | scopeSlots: PlcScopeSlotsOptions, 12 | emits: PlcEmitsOptions, 13 | setup({props, slots, scopeSlots, event}) { 14 | return useBasePlc({props, scopeSlots, event, slots}) 15 | }, 16 | expose: { 17 | applyPropsState, 18 | getPropsState, 19 | }, 20 | }) 21 | 22 | export default Plc 23 | -------------------------------------------------------------------------------- /src/packages/PlTabs/header/vertical/TabsHeaderVertical.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, useClasses} from "plain-ui-composition"; 2 | import './tabs-header-vertical.scss' 3 | import {TabCommonProps} from "../../tabs.utils"; 4 | 5 | export const PlTabsHeaderVertical = designComponent({ 6 | props: { 7 | ...TabCommonProps, 8 | }, 9 | slots: ['default'], 10 | setup({props, slots}) { 11 | 12 | const classes = useClasses(() => [ 13 | 'pl-tabs-header', 14 | 'pl-tabs-header-vertical', 15 | `pl-tabs-header-pos-${props.headPosition}`, 16 | ]) 17 | 18 | return () => ( 19 |
20 | {slots.default()} 21 |
22 | ) 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /src/packages/PlTabs/tabs.utils.tsx: -------------------------------------------------------------------------------- 1 | import {PropType} from "plain-ui-composition"; 2 | import {PlTabComponent} from "../PlTab"; 3 | 4 | export enum TabHeadType { 5 | text = 'text', 6 | card = 'card', 7 | shadow = 'shadow', 8 | } 9 | 10 | export enum TabHeadPosition { 11 | top = 'top', 12 | bottom = 'bottom', 13 | left = 'left', 14 | right = 'right', 15 | } 16 | 17 | export const TabCommonProps = { 18 | headType: {type: String as PropType, default: TabHeadType.text}, // 页签样式 19 | headPosition: {type: String as PropType, default: TabHeadPosition.top}, // 页签位置 20 | } 21 | 22 | export type TabData = { item: PlTabComponent, index: number, active: boolean } 23 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-place.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/utils/constant.tsx: -------------------------------------------------------------------------------- 1 | export enum CheckboxStatus { 2 | uncheck = 'uncheck', 3 | check = 'check', 4 | minus = 'minus', 5 | } 6 | 7 | export const STATUS = { 8 | white: {icon: 'el-icon-info', status: 'white'}, 9 | black: {icon: 'el-icon-info', status: 'black'}, 10 | lite: {icon: 'el-icon-info', status: 'white'}, 11 | dark: {icon: 'el-icon-info', status: 'black'}, 12 | primary: {icon: 'el-icon-info', status: 'primary'}, 13 | success: {icon: 'el-icon-success', status: 'success'}, 14 | warn: {icon: 'el-icon-warning', status: 'warn'}, 15 | error: {icon: 'el-icon-error', status: 'error'}, 16 | info: {icon: 'el-icon-info', status: 'info'}, 17 | } as { [k: string]: { icon: string, status: string } } 18 | 19 | export const noop = () => void 0 20 | -------------------------------------------------------------------------------- /story/story.utils.ts: -------------------------------------------------------------------------------- 1 | export const StoryStatus = [ 2 | {label: '基础', status: 'primary' as 'primary'}, 3 | {label: '成功', status: 'success' as 'success'}, 4 | {label: '警告', status: 'warn' as 'warn'}, 5 | {label: '失败', status: 'error' as 'error'}, 6 | {label: '帮助', status: 'info' as 'info'}, 7 | ] 8 | 9 | export const StoryShapes = [ 10 | {label: '圆角', shape: 'fillet' as 'fillet'}, 11 | {label: '圆形', shape: 'round' as 'round'}, 12 | {label: '方角', shape: 'square' as 'square'}, 13 | ] 14 | export const StorySizes = [ 15 | {label: '大', size: 'large' as 'large'}, 16 | {label: '中', size: 'normal' as 'normal'}, 17 | {label: '小', size: 'mini' as 'mini'}, 18 | ] 19 | 20 | export const Modes = [ 21 | 'fill', 22 | 'stroke', 23 | 'text', 24 | ] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-first-aid-kit.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-refresh.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/use/useFunctionWrapper.ts: -------------------------------------------------------------------------------- 1 | import {getCurrentInstance} from 'vue' 2 | 3 | export function useFunctionWrapper

any>( 5 | key: string, 6 | func: T, 7 | ): (...args: P) => ReturnType { 8 | return (...args) => { 9 | const ctx = getCurrentInstance() as any 10 | if (!ctx._use) ctx._use = {} 11 | 12 | if (!!ctx._use[key]) { 13 | throw new Error(`use ${key} can only be executed once!`) 14 | } 15 | 16 | return (ctx._use[key] = func(ctx, ...args)) 17 | } 18 | } 19 | 20 | /*const func = useFunctionWrapper('', (ctx, name: string, age: number) => { 21 | return { 22 | sayHello: () => {}, 23 | } 24 | }) 25 | 26 | const data = func('111', 111) 27 | data.sayHello()*/ 28 | 29 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-thumb.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlColorPicker/color-picker.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | 3 | .pl-color-button { 4 | border-radius: 2px; 5 | height: 24px; 6 | width: 24px; 7 | border: solid 1px $ibc; 8 | padding: 2px; 9 | box-sizing: border-box; 10 | display: inline-block; 11 | cursor: pointer; 12 | 13 | .pl-color-button-background { 14 | background-size: 7px 7px; 15 | border-radius: 2px; 16 | box-sizing: border-box; 17 | height: 100%; 18 | width: 100%; 19 | 20 | .pl-color-button-color { 21 | height: 100%; 22 | width: 100%; 23 | } 24 | } 25 | } 26 | 27 | .pl-color-picker { 28 | @include sizeMixin(input) { 29 | .pl-color-button { 30 | height: $value/2; 31 | width: $value/2; 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/packages/PlTable/plc/format/process/copyPlcList.ts: -------------------------------------------------------------------------------- 1 | import {tPlcType} from "../../utils/plc.type"; 2 | import {deepcopy} from "plain-utils/object/deepcopy"; 3 | import {PlcPublicAttrs} from "../../utils/plc.utils"; 4 | 5 | /** 6 | * 浅复制一份plc数据,复制plc最外层对象以及plc.props数据,props数据是需要动态计算修改的。 7 | * state不能复制,因为需要其响应式属性。 8 | * @author 韦胜健 9 | * @date 2020/12/18 10:06 10 | */ 11 | export function copyPlcList(plcList: tPlcType[]) { 12 | return plcList.map(plc => { 13 | const refer = plc.refer() 14 | const newPlc: tPlcType = { 15 | ...refer, 16 | ...deepcopy(PlcPublicAttrs), 17 | } 18 | newPlc.props = {...newPlc.props} 19 | if (newPlc.group) { 20 | newPlc.children = copyPlcList(newPlc.children) 21 | } 22 | return newPlc 23 | }) 24 | } -------------------------------------------------------------------------------- /src/packages/PlRate/rate.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-rate { 3 | position: relative; 4 | display: inline-block; 5 | cursor: pointer; 6 | overflow: hidden; 7 | vertical-align: text-bottom; 8 | 9 | .pl-rate-active { 10 | white-space: nowrap; 11 | overflow: hidden; 12 | position: absolute; 13 | left: 0; 14 | top: 0; 15 | bottom: 0; 16 | } 17 | 18 | @include statusMixin(rate) { 19 | color: $value; 20 | } 21 | 22 | &.pl-rate-disabled { 23 | color: $disabledText !important; 24 | cursor: not-allowed; 25 | } 26 | 27 | &.pl-rate-size-min { 28 | font-size: 14px; 29 | } 30 | 31 | &.pl-rate-size-normal { 32 | font-size: 16px; 33 | } 34 | 35 | &.pl-rate-size-large { 36 | font-size: 18px; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /story/pages/normal/DemoIcon.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition"; 2 | import {DemoRow} from "../../components/DemoRow"; 3 | import {PlIcon} from "../../../src/packages/PlIcon"; 4 | 5 | export default designComponent({ 6 | setup() { 7 | return () => ( 8 |

9 | 10 | 普通的文本:NORMAL normal 11 | 12 | 13 | 14 | 15 | 16 | {['primary', 'success', 'warn', 'error', 'info'].map(status => )} 17 | 18 |
19 | ) 20 | }, 21 | }) 22 | -------------------------------------------------------------------------------- /src/packages/PlCollapse/collapse.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | 3 | .pl-collapse { 4 | .pl-collapse-title { 5 | font-size: 16px; 6 | color: $colorPrimary; 7 | padding: 16px 0; 8 | border-bottom: solid 1px $ibl; 9 | display: flex; 10 | align-items: center; 11 | 12 | .pl-icon { 13 | margin-right: 4px; 14 | } 15 | 16 | & > * { 17 | cursor: pointer; 18 | } 19 | } 20 | 21 | &.pl-collapse-is-open { 22 | .pl-collapse-title { 23 | & > .pl-icon:first-child { 24 | transform: rotate(90deg); 25 | } 26 | } 27 | } 28 | } 29 | 30 | .pl-collapse-group { 31 | border-bottom: solid 1px $ibl; 32 | 33 | .pl-collapse-title { 34 | border-bottom: none; 35 | border-top: solid 1px $ibl; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /story/components/DemoRow.utils.ts: -------------------------------------------------------------------------------- 1 | const DEMO_ROW_STORAGE_KEY = 'DEMO_ROW' 2 | 3 | export const DemoRowCache = (() => { 4 | let str = localStorage.getItem(DEMO_ROW_STORAGE_KEY) 5 | const cache: Record = !!str ? JSON.parse(str) : {} 6 | 7 | return { 8 | get: (id: string) => { 9 | const flag = cache[id] 10 | return flag == null ? true : flag 11 | }, 12 | set: (id: string, flag: boolean) => { 13 | cache[id] = flag 14 | localStorage.setItem(DEMO_ROW_STORAGE_KEY, JSON.stringify(cache)) 15 | }, 16 | setAll: (flag: boolean) => { 17 | for (const key in cache) { 18 | cache[key] = flag 19 | } 20 | localStorage.setItem(DEMO_ROW_STORAGE_KEY, JSON.stringify(cache)) 21 | }, 22 | } 23 | })() -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "skipLibCheck": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env" 16 | ], 17 | "lib": [ 18 | "esnext", 19 | "dom", 20 | "dom.iterable", 21 | "scripthost" 22 | ] 23 | }, 24 | "include": [ 25 | "src/**/*.ts", 26 | "src/**/*.tsx", 27 | "src/**/*.vue", 28 | "story/**/*.ts", 29 | "story/**/*.tsx", 30 | "story/**/*.vue", 31 | "tests/**/*.ts", 32 | "tests/**/*.tsx" 33 | ], 34 | "exclude": [ 35 | "node_modules" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /src/packages/PlTablePro/table-pro.scss: -------------------------------------------------------------------------------- 1 | .pl-table-pro-pagination { 2 | padding: 16px 24px; 3 | 4 | .pl-pagination { 5 | justify-content: flex-end; 6 | } 7 | } 8 | 9 | .pl-table-pro-head { 10 | font-size: 14px; 11 | height: 56px; 12 | display: flex; 13 | align-items: center; 14 | justify-content: space-between; 15 | padding: 0 24px; 16 | 17 | .pl-table-pro-title { 18 | .pl-icon { 19 | margin-right: 4px; 20 | } 21 | } 22 | 23 | .pl-table-pro-operation { 24 | min-width: 350px; 25 | text-align: right; 26 | 27 | & > .pl-button { 28 | margin-left: 4px; 29 | } 30 | } 31 | } 32 | 33 | .pl-table-pro-fill { 34 | height: 100%; 35 | flex: 1; 36 | display: flex; 37 | flex-direction: column; 38 | 39 | .pl-table-pro-base-table { 40 | flex: 1; 41 | overflow: hidden; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/packages/PlTagInput/tag-input.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-tag-input { 3 | display: inline-block; 4 | 5 | .pl-tag { 6 | //margin-bottom: 8px; 7 | 8 | &:not(:last-child) { 9 | margin-right: 8px; 10 | } 11 | } 12 | 13 | .pl-input { 14 | //margin-bottom: 8px; 15 | 16 | .pl-input-inner { 17 | border-style: dashed; 18 | width: 100% !important; 19 | } 20 | } 21 | 22 | .pl-tag-input-not-edit { 23 | text-align: center; 24 | cursor: pointer; 25 | } 26 | 27 | @include statusMixin(tag-input) { 28 | .pl-tag-input-not-edit { 29 | color: $value; 30 | } 31 | } 32 | 33 | &.pl-tag-input-disabled { 34 | .pl-tag-input-not-edit { 35 | cursor: not-allowed; 36 | color: $disabledText; 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /story/pages/normal/DemoCheckbox.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .demo-checkbox { 3 | .demo-checkbox-row { 4 | & > * { 5 | margin-right: 1em; 6 | } 7 | } 8 | 9 | .demo-checkbox-custom-item { 10 | display: inline-flex; 11 | height: 80px; 12 | width: 80px; 13 | border-radius: 4px; 14 | border: solid 1px #f1f1f1; 15 | align-items: center; 16 | justify-content: center; 17 | background-color: #f1f1f1; 18 | cursor: pointer; 19 | user-select: none; 20 | transition: all 300ms $transition; 21 | 22 | &.demo-checkbox-custom-item-active { 23 | background-color: $colorPrimary; 24 | color: white; 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /story/app/navigator.utils.ts: -------------------------------------------------------------------------------- 1 | import {reactive} from "vue" 2 | 3 | export type AppRoute = { 4 | path: string, 5 | hash: string, 6 | } 7 | 8 | const getRoute = (): AppRoute => { 9 | let uri = decodeURIComponent(window.location.hash || '') 10 | if (uri.charAt(0) === '#' && uri.length > 0) {uri = uri.substring(1)} 11 | let [path, hash] = uri.split('#') 12 | if (!!path && path.charAt(0) === '/') { 13 | path = path.slice(1) 14 | } 15 | return { 16 | path, 17 | hash, 18 | } 19 | } 20 | 21 | export const Router = (() => { 22 | const state = reactive({ 23 | route: getRoute(), 24 | go: (path: string) => {window.location.hash = encodeURIComponent(path)}, 25 | }) 26 | window.addEventListener('hashchange', () => { 27 | state.route = getRoute() 28 | }) 29 | return state 30 | })(); -------------------------------------------------------------------------------- /src/packages/PlTable/plc/edit/plc-input.tsx: -------------------------------------------------------------------------------- 1 | 2 | import {PlInput} from "../../../PlInput"; 3 | import {designComponent} from "plain-ui-composition"; 4 | import {PlcEmitsOptions, PlcPropsOptions} from "../utils/plc.utils"; 5 | import {PlcScopeSlotsOptions} from "../utils/plc.scope-slots"; 6 | import {useExternalPlc} from "../core/useExternalPlc"; 7 | 8 | export default designComponent({ 9 | name: 'plc-input', 10 | props: { 11 | ...PlcPropsOptions, 12 | }, 13 | scopeSlots: PlcScopeSlotsOptions, 14 | emits: PlcEmitsOptions, 15 | setup({props, slots, scopeSlots, event}) { 16 | return useExternalPlc({ 17 | props, scopeSlots, slots, event, defaultScopeSlots: { 18 | edit: ({row, plc}) => !plc.props.field ? null : 19 | } 20 | }) 21 | }, 22 | }) 23 | -------------------------------------------------------------------------------- /src/packages/PlDate/useDate.tsx: -------------------------------------------------------------------------------- 1 | import {PlDatePanel} from "./panel/PlDatePanel"; 2 | import {createUseEditPopperAgent} from "../useEditPopperAgent/createAgentGetter"; 3 | 4 | export const useDate = createUseEditPopperAgent({ 5 | name: 'date', 6 | render: (attrs) => , 7 | defaultPopperAttrs: { 8 | transition: 'pl-transition-popper-drop', 9 | }, 10 | defaultRenderAttrs: { 11 | async onChange() { 12 | let renderAttrs: any = this.state.option.serviceOption.renderAttrs 13 | if (typeof renderAttrs === "function") renderAttrs = renderAttrs() 14 | if (!( 15 | renderAttrs.datetime || 16 | renderAttrs.multiple || 17 | renderAttrs.range 18 | )) { 19 | this.hide() 20 | } 21 | }, 22 | }, 23 | }) 24 | -------------------------------------------------------------------------------- /src/packages/PlSelect/useSelect.tsx: -------------------------------------------------------------------------------- 1 | import {createUseEditPopperAgent} from "../useEditPopperAgent/createAgentGetter"; 2 | import {PlSelectPanel} from "./PlSelectPanel"; 3 | 4 | export const useSelect = createUseEditPopperAgent({ 5 | name: 'select', 6 | render: (attrs) => { 7 | return 8 | }, 9 | defaultPopperAttrs: { 10 | transition: 'pl-transition-popper-drop', 11 | sizeEqual: true, 12 | arrow: false, 13 | }, 14 | defaultRenderAttrs: { 15 | async onChange() { 16 | let renderAttrs: any = this.state.option.serviceOption.renderAttrs 17 | if (typeof renderAttrs === "function") renderAttrs = renderAttrs() 18 | /*非多选的情况下,默认点击关闭下拉框*/ 19 | if (!renderAttrs.multiple) { 20 | this.hide() 21 | } 22 | } 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /src/packages/PlTime/panel/time-base-panel.scss: -------------------------------------------------------------------------------- 1 | @import "./time.public"; 2 | 3 | @include theme { 4 | .pl-time-base-panel { 5 | display: inline-block; 6 | position: relative; 7 | color: $itc; 8 | 9 | &:before { 10 | position: absolute; 11 | top: $time-size*3; 12 | left: 0; 13 | right: 0; 14 | height: 1px; 15 | background-color: $ibl; 16 | content: ''; 17 | pointer-events: none; 18 | } 19 | 20 | &:after { 21 | position: absolute; 22 | top: $time-size*4; 23 | left: 0; 24 | right: 0; 25 | height: 1px; 26 | background-color: $ibl; 27 | content: ''; 28 | pointer-events: none; 29 | } 30 | 31 | .pl-time-base-column { 32 | border: none; 33 | 34 | & + .pl-time-base-column { 35 | border-left: dashed 1px $ibc; 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/packages/PlTime/time.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-time { 3 | .pl-time-inner { 4 | display: flex; 5 | align-items: stretch; 6 | height: 100%; 7 | 8 | & > span { 9 | color: $icc; 10 | } 11 | 12 | .pl-time-input-inner { 13 | border: none; 14 | outline: none; 15 | width: 90px; 16 | height: 100%; 17 | background: transparent; 18 | } 19 | } 20 | 21 | &.pl-time-range { 22 | .pl-time-input-inner { 23 | text-align: center; 24 | } 25 | } 26 | 27 | .pl-input-inner { 28 | width: auto !important; 29 | } 30 | } 31 | 32 | .pl-time-panel-foot { 33 | padding: 8px 8px 0 8px; 34 | border-top: solid 1px $ibl; 35 | display: flex; 36 | justify-content: center; 37 | 38 | & > * + * { 39 | margin-left: 8px; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-view.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlColorPicker/sub/color-alpha-slider.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-color-alpha-slider { 3 | width: 10px; 4 | background-size: 10px 10px; 5 | position: relative; 6 | cursor: pointer; 7 | border-radius: 10px; 8 | display: inline-block; 9 | 10 | .pl-color-alpha-shadow, .pl-color-alpha-thumb { 11 | pointer-events: none; 12 | } 13 | 14 | .pl-color-alpha-shadow { 15 | position: absolute; 16 | top: 0; 17 | left: 0; 18 | right: 0; 19 | bottom: 0; 20 | border-radius: 10px; 21 | } 22 | 23 | .pl-color-alpha-thumb { 24 | width: 10px; 25 | height: 10px; 26 | border-radius: 10px; 27 | border: solid 1px $colorInfo; 28 | display: inline-block; 29 | background-color: white; 30 | position: absolute; 31 | top: 0; 32 | left: 0; 33 | box-sizing: border-box; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-rank.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/pages/table-pro/table-files.tsx: -------------------------------------------------------------------------------- 1 | import {designPage} from "plain-ui-composition"; 2 | 3 | import useTableOption from "../../init/useTableOption"; 4 | import {Plc, PlcDate, PlTablePro} from "../../../src"; 5 | 6 | export const demo1 = designPage(() => { 7 | 8 | const option = useTableOption({ 9 | url: '/upload', 10 | fill: true, 11 | enable: { 12 | insert: false, 13 | update: false, 14 | }, 15 | }) 16 | 17 | return () => <> 18 |
19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | }) 28 | -------------------------------------------------------------------------------- /src/packages/PlTooltip/tooltip.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-tooltip { 3 | .plain-popper-content .pl-popper-content-inner { 4 | color: inherit; 5 | padding: 8px 12px !important; 6 | } 7 | 8 | &.pl-tooltip-theme-dark { 9 | .plain-popper-content { 10 | background-color: black !important; 11 | 12 | &, & .pl-popper-content-inner, & .pl-popper-title { 13 | color: white; 14 | } 15 | } 16 | } 17 | 18 | &.pl-tooltip-theme-light { 19 | .plain-popper-content { 20 | background-color: white !important; 21 | 22 | &, & .pl-popper-content-inner { 23 | color: $itc !important; 24 | } 25 | } 26 | } 27 | } 28 | 29 | .pl-tooltip-reference { 30 | display: inline-block; 31 | overflow: hidden; 32 | text-overflow: ellipsis; 33 | white-space: nowrap; 34 | vertical-align: baseline; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/packages/PlDropdownMenu/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition"; 2 | import PlDropdown from "../PlDropdown"; 3 | 4 | export const PlDropdownMenu = designComponent({ 5 | name: 'pl-dropdown-menu', 6 | props: {}, 7 | emits: { 8 | onClickOption: (e: MouseEvent, val: any) => true, 9 | }, 10 | slots: ['default'], 11 | provideRefer: true, 12 | setup({props, slots, event: {emit}}) { 13 | 14 | const dropdown = PlDropdown.use.inject() 15 | 16 | const handler = { 17 | clickOption: (e: MouseEvent, val: any) => { 18 | emit.onClickOption(e, val) 19 | dropdown.handler.clickDropdownOption(e) 20 | } 21 | } 22 | 23 | return { 24 | refer: { 25 | handler, 26 | }, 27 | render: slots.default 28 | } 29 | }, 30 | }) 31 | 32 | export default PlDropdownMenu 33 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-alarm-clock.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlPopper/refershPopperReference.tsx: -------------------------------------------------------------------------------- 1 | import {inject, provide} from "plain-ui-composition" 2 | import {SimpleFunction} from "plain-ui-composition" 3 | 4 | const REFRESH_POPPER_REFERENCE = '@@REFRESH_POPPER_REFERENCE' 5 | 6 | /** 7 | * 因为 Popper 是无根节点,所以比较难检测到reference节点变化的情况。为了优化这一块的内容 8 | * 有两种方式,一种是在使用Popper组件的时候,reference包裹一层不变的节点,缺点是会破坏无根 9 | * 节点的结构。另一种是,提供一个 refreshPopperReference 函数,子组件可以注入这个函数,当子组件 10 | * 知道自己的reference节点变化之后调用这个函数通知Popper重新reference。 11 | * 12 | * @author 韦胜健 13 | * @date 2020/11/19 11:00 14 | */ 15 | export const refreshPopperReference = { 16 | provide: (refresh: SimpleFunction) => { 17 | provide(REFRESH_POPPER_REFERENCE, refresh) 18 | }, 19 | inject: (defaultValue = null) => { 20 | const refresh = inject(REFRESH_POPPER_REFERENCE, defaultValue) as null | SimpleFunction 21 | return { 22 | freshPopperReference: () => !!refresh && refresh() 23 | } 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /src/packages/PlColorPicker/color-panel.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-color-panel { 3 | display: inline-block; 4 | font-size: 0; 5 | padding: 8px 12px; 6 | 7 | & > div:first-child { 8 | white-space: nowrap; 9 | } 10 | 11 | .pl-color-hue-slider { 12 | margin-top: 8px; 13 | display: block; 14 | } 15 | 16 | .pl-color-alpha-slider { 17 | margin-left: 8px; 18 | } 19 | 20 | .pl-color-panel-input-group { 21 | margin-top: 8px; 22 | 23 | .pl-input { 24 | 25 | .pl-input-inner { 26 | text-align: center; 27 | border-top-right-radius: 0; 28 | border-bottom-right-radius: 0; 29 | border-right: none; 30 | } 31 | } 32 | 33 | .pl-button-group { 34 | & > .pl-button:first-child { 35 | border-top-left-radius: 0; 36 | border-bottom-left-radius: 0; 37 | border-left: none; 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/packages/initialize/index.tsx: -------------------------------------------------------------------------------- 1 | import {tUseTableOption} from "../createUseTableOption"; 2 | import {iUseHttp} from "../useHttp/useHttp.utils"; 3 | import {iUseAddressConfig} from "../useAddress/useAddress.utils"; 4 | import {iUseOvConfig} from "../useOv/useOv.utils"; 5 | 6 | export interface InitializeConfigState { 7 | useTableOption: tUseTableOption, 8 | useObjectOption: tUseTableOption, 9 | useHttp: iUseHttp, 10 | useAddressConfig: iUseAddressConfig, 11 | useOvConfig: iUseOvConfig, 12 | getExceljs: () => Promise, 13 | getFileSaver: () => Promise, 14 | } 15 | 16 | let state: InitializeConfigState | null = null 17 | 18 | export function initialize(getter: () => InitializeConfigState) {state = getter()} 19 | 20 | export function getInitialConfigState(k: K) { 21 | if (!state) {throw new Error('请先调用 initialize 初始化 InitializeConfigState')} 22 | return state[k] 23 | } 24 | 25 | export default initialize 26 | -------------------------------------------------------------------------------- /src/packages/PlTable/plc/edit/plc-number.tsx: -------------------------------------------------------------------------------- 1 | 2 | import {PlNumber} from "../../../PlNumber"; 3 | import {designComponent} from "plain-ui-composition"; 4 | import {PlcEmitsOptions, PlcPropsOptions} from "../utils/plc.utils"; 5 | import {PlcScopeSlotsOptions} from "../utils/plc.scope-slots"; 6 | import {useExternalPlc} from "../core/useExternalPlc"; 7 | 8 | export default designComponent({ 9 | name: 'plc-number', 10 | props: { 11 | ...PlcPropsOptions, 12 | filterName: {type: String, default: 'number'}, 13 | filterHandler: {type: String, default: '范围'}, 14 | }, 15 | scopeSlots: PlcScopeSlotsOptions, 16 | emits: PlcEmitsOptions, 17 | setup({props, slots, scopeSlots, event}) { 18 | return useExternalPlc({ 19 | props, scopeSlots, slots, event, defaultScopeSlots: { 20 | edit: ({row, plc}) => !plc.props.field ? null : 21 | } 22 | }) 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-debug.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlCascadePanel/useCascade.tsx: -------------------------------------------------------------------------------- 1 | import './cascade-service.scss' 2 | import {createUseEditPopperAgent} from "../useEditPopperAgent/createAgentGetter"; 3 | import PlCascadePanel from "./index"; 4 | import {delay} from "plain-utils/utils/delay"; 5 | 6 | export const useCascade = createUseEditPopperAgent({ 7 | name: 'cascade', 8 | render(attrs) { 9 | return 10 | }, 11 | defaultPopperAttrs: { 12 | transition: 'pl-transition-popper-drop', 13 | }, 14 | defaultRenderAttrs: { 15 | async onChange() { 16 | let renderAttrs: any = this.state.option.serviceOption.renderAttrs 17 | if (typeof renderAttrs === "function") renderAttrs = renderAttrs() 18 | if (!renderAttrs.selectBranch) { 19 | // 因为change之后,会引发 cascade panels 重新渲染没有宽度以及高度,导致过度动画失效,这里再change之后延迟再关闭 20 | await delay(120) 21 | this.hide() 22 | } 23 | }, 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /src/packages/PlTabs/tabs.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-tabs { 3 | .pl-tabs-collector { 4 | height: 0; 5 | width: 0; 6 | overflow: hidden; 7 | display: block; 8 | } 9 | 10 | .pl-tabs-header-item { 11 | cursor: pointer; 12 | user-select: none; 13 | 14 | .pl-icon { 15 | margin-left: 8px; 16 | } 17 | 18 | &:not(.pl-tabs-header-item-active) { 19 | .pl-icon { 20 | color: $icc; 21 | } 22 | } 23 | } 24 | 25 | .pl-tabs-header-item-operator { 26 | flex-grow: 1; 27 | flex-shrink: 0; 28 | position: sticky; 29 | right: 4px; 30 | height: 45px; 31 | line-height: 45px; 32 | padding-left: 16px; 33 | justify-self: flex-end; 34 | display: inline-flex; 35 | align-items: center; 36 | justify-content: flex-end; 37 | background-color: white; 38 | 39 | & > * + * { 40 | margin-left: 4px; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-chat-dot-round.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/app/AppNavigator.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, reactive, watch} from 'plain-ui-composition' 2 | import {Fragment} from 'vue' 3 | import {Router} from "./navigator.utils"; 4 | 5 | export const AppNavigator = designComponent({ 6 | setup() { 7 | 8 | const state = reactive({ 9 | Page: null as any 10 | }) 11 | 12 | watch(() => Router.route.path, async (path) => { 13 | if (!path) path = 'normal/DemoButton' 14 | if (path.charAt(0) === '/') {path = path.slice(1)} 15 | 16 | const Components = Object.values(await import('../pages/' + path)) as any[] 17 | state.Page = Components.map((Component, index) => ( 18 | 19 | 20 | 21 | )) 22 | }, {immediate: true}) 23 | 24 | return () => ( 25 |
26 | {state.Page} 27 |
28 | ) 29 | }, 30 | }) 31 | -------------------------------------------------------------------------------- /src/packages/PlRadioInner/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, useClasses, useRefs} from "plain-ui-composition" 2 | import './radio-inner.scss' 3 | 4 | export const PlRadioInner = designComponent({ 5 | name: 'pl-radio-inner', 6 | props: { 7 | checkStatus: {type: String}, // check,uncheck 8 | }, 9 | inheritPropsType: SVGElement, 10 | setup({props}) { 11 | 12 | const {refs, onRef} = useRefs({el: SVGElement}) 13 | 14 | const classes = useClasses(() => [ 15 | 'pl-radio-inner', 16 | `pl-radio-inner-${props.checkStatus}`, 17 | ]) 18 | 19 | return { 20 | refer: {refs}, 21 | render: () => ( 22 | 23 | {props.checkStatus === 'check' && } 24 | 25 | ) 26 | } 27 | }, 28 | }) 29 | 30 | export default PlRadioInner 31 | -------------------------------------------------------------------------------- /src/packages/createUseTableOption/use/filter/distinct.filter.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-table-pro-distinct-filter-item { 3 | display: flex; 4 | align-items: stretch; 5 | line-height: 28px; 6 | 7 | padding: 8px 0; 8 | 9 | background-color: white; 10 | transition: background-color 300ms linear; 11 | 12 | &:not(:last-child) { 13 | border-bottom: solid 1px $ibl; 14 | } 15 | 16 | &:hover { 17 | background-color: #f6f6f6; 18 | } 19 | 20 | .pl-table-pro-distinct-filter-item-title { 21 | color: $colorPrimary; 22 | margin: 0 8px; 23 | } 24 | 25 | .pl-table-pro-distinct-filter-item-tags { 26 | 27 | cursor: pointer; 28 | 29 | & > div { 30 | display: inline-block; 31 | font-size: 12px; 32 | background-color: $colorPrimaryLight; 33 | padding: 0 12px; 34 | margin: 1px 2px; 35 | border-radius: 4px; 36 | } 37 | } 38 | 39 | .pl-table-pro-distinct-filter-item-button { 40 | 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/packages/PlTable/plc/edit/plc-rate.tsx: -------------------------------------------------------------------------------- 1 | 2 | import {PlRate} from "../../../PlRate"; 3 | import {designComponent} from "plain-ui-composition"; 4 | import {createPlcPropOptions, PlcEmitsOptions} from "../utils/plc.utils"; 5 | import {PlcScopeSlotsOptions} from "../utils/plc.scope-slots"; 6 | import {useExternalPlc} from "../core/useExternalPlc"; 7 | 8 | export default designComponent({ 9 | name: 'plc-rate', 10 | props: { 11 | ...createPlcPropOptions({ 12 | addEditPadding: true, 13 | }), 14 | }, 15 | scopeSlots: PlcScopeSlotsOptions, 16 | emits: PlcEmitsOptions, 17 | setup({props, slots, scopeSlots, event}) { 18 | return useExternalPlc({ 19 | props, scopeSlots, slots, event, defaultScopeSlots: { 20 | normal: ({row, plc}) => !plc.props.field ? null : , 21 | edit: ({row, plc}) => !plc.props.field ? null : , 22 | } 23 | }) 24 | }, 25 | }) 26 | -------------------------------------------------------------------------------- /src/packages/PlEmpty/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, useStyles} from "plain-ui-composition"; 2 | 3 | // @ts-ignore 4 | import NO_DATA_IMG from './assets/no_data.svg' 5 | import './empty.scss' 6 | 7 | export const PlEmpty = designComponent({ 8 | name: 'pl-empty', 9 | props: { 10 | height: {type: String, default: '200px'}, 11 | fontSize: {type: String, default: '14px'}, 12 | label: {type: String, default: '暂无数据...'}, 13 | }, 14 | slots: ['labelContent'], 15 | setup({props}) { 16 | 17 | const styles = useStyles(styles => { 18 | styles.fontSize = props.fontSize 19 | }) 20 | const imgStyles = useStyles((styles) => { 21 | styles.height = props.height 22 | }) 23 | 24 | return () => ( 25 |
26 | 27 | {props.label} 28 |
29 | ) 30 | }, 31 | }) 32 | 33 | export default PlEmpty 34 | -------------------------------------------------------------------------------- /src/packages/createUseTableOption/use/setting/use.setting.filter.all.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-table-pro-setting-all-filter { 3 | 4 | background-color: #fafafa; 5 | min-height: 100%; 6 | width: 100%; 7 | display: inline-block; 8 | box-sizing: border-box; 9 | padding: 16px; 10 | 11 | & > * { 12 | margin-bottom: 16px; 13 | 14 | &:first-child { 15 | text-align: right; 16 | } 17 | } 18 | 19 | .pl-table-pro-setting-all-filter-item { 20 | background-color: white; 21 | box-sizing: border-box; 22 | border-radius: 2px; 23 | box-shadow: 1px 1px 8px 1px #e2e3e4; 24 | 25 | .pl-table-pro-setting-all-filter-item-head { 26 | font-size: 16px; 27 | font-weight: 600; 28 | border-bottom: solid 1px $ibl; 29 | padding: 16px; 30 | display: flex; 31 | justify-content: space-between; 32 | } 33 | 34 | .pl-table-pro-setting-all-filter-item-body { 35 | padding: 16px; 36 | } 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/utils/ClickBodyListener.tsx: -------------------------------------------------------------------------------- 1 | interface ClickListener { 2 | (e: MouseEvent): void 3 | } 4 | 5 | export const ClickBodyListener = (() => { 6 | 7 | const state = { 8 | handlers: [] as ClickListener[], 9 | disabled: false, 10 | } 11 | 12 | const onClickBody = (e: MouseEvent) => { 13 | if (state.disabled) {return} 14 | state.handlers.forEach(h => h(e)) 15 | } 16 | 17 | document.body.addEventListener('click', onClickBody, true) 18 | 19 | const disable = () => state.disabled = true 20 | const enable = () => state.disabled = false 21 | const listen = (handler: ClickListener) => { 22 | state.handlers.indexOf(handler) === -1 && state.handlers.push(handler) 23 | return () => eject(handler) 24 | } 25 | const eject = (handler: ClickListener) => { 26 | const index = state.handlers.indexOf(handler) 27 | index >= 1 && state.handlers.splice(index, 1) 28 | } 29 | 30 | return { 31 | disable, 32 | enable, 33 | listen, 34 | eject, 35 | } 36 | })(); -------------------------------------------------------------------------------- /src/packages/PlTable/table/use/useBindScroll.ts: -------------------------------------------------------------------------------- 1 | import {TableHoverPart} from "../utils/table.utils"; 2 | import {ref} from "plain-ui-composition"; 3 | 4 | /** 5 | * 绑定表头表体联动滚动 6 | * @author 韦胜健 7 | * @date 2020/12/18 16:27 8 | */ 9 | export function useBindScroll( 10 | event: { 11 | emit: { 12 | onScrollLeft: (scrollLeft: number, part: TableHoverPart) => void, 13 | }, 14 | on: { 15 | onScrollLeft: (cb: (scrollLeft: number, part: TableHoverPart) => void) => void, 16 | }, 17 | } 18 | ) { 19 | const hoverPart = ref(null as null | TableHoverPart) 20 | return { 21 | bindScroll: (part: TableHoverPart, updateLeft: (left: number, part: TableHoverPart) => void) => { 22 | event.on.onScrollLeft((left, part) => updateLeft(left, part)) 23 | return { 24 | onMouseenter: () => hoverPart.value = part, 25 | onScroll: (e: Event) => hoverPart.value === part && event.emit.onScrollLeft((e as any).target.scrollLeft, part) 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/packages/PlLoadingMask/loading-mask.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-loading-mask { 3 | color: $colorPrimary; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | flex-direction: column; 8 | position: absolute; 9 | top: 0; 10 | left: 0; 11 | right: 0; 12 | bottom: 0; 13 | background-color: rgba(255, 255, 255, 0.5); 14 | transition: all linear 300ms; 15 | transform-origin: center center; 16 | cursor: progress; 17 | pointer-events: auto; 18 | 19 | .pl-loading { 20 | margin-bottom: 20px; 21 | font-size: 32px; 22 | 23 | & + span { 24 | font-size: 14px; 25 | } 26 | } 27 | 28 | &.pl-loading-mask-unlock { 29 | pointer-events: none; 30 | } 31 | 32 | &.pl-loading-mask-fixed-position { 33 | position: fixed; 34 | } 35 | } 36 | } 37 | 38 | .pl-transition-loading-mask-enter-active, .pl-transition-loading-mask-leave-active { 39 | opacity: 1; 40 | } 41 | 42 | .pl-transition-loading-mask-enter-from, .pl-transition-loading-mask-leave-to { 43 | opacity: 0; 44 | } -------------------------------------------------------------------------------- /src/packages/PlTable/plc/standard/draggier/core/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 获取拖拽的rowEl对象 3 | * @author 韦胜健 4 | * @date 2020/8/19 23:55 5 | */ 6 | import {hasClass} from "plain-utils/dom/hasClass"; 7 | 8 | export function getRowEl(e: MouseEvent, rowClass: string): HTMLElement { 9 | let rowEl = e.target as HTMLElement 10 | while (!!rowEl && !hasClass(rowEl, rowClass)) { 11 | rowEl = rowEl.parentNode as HTMLElement 12 | } 13 | if (!rowEl) { 14 | throw new Error(`can't find item element!`) 15 | } 16 | return rowEl 17 | } 18 | 19 | /** 20 | * 获取可以滚动的父组件 21 | * @author 韦胜健 22 | * @date 2020/8/19 23:50 23 | */ 24 | export function getScrollParent(el: HTMLElement): HTMLElement { 25 | while (!!el && el.scrollHeight <= el.offsetHeight) { 26 | el = el.parentNode as HTMLElement 27 | } 28 | return el 29 | } 30 | 31 | /** 32 | * 获取行el对象的所有兄弟节点 33 | * @author 韦胜健 34 | * @date 2020/8/19 23:57 35 | */ 36 | export function getRowElList(el: HTMLElement, rowClass: string): HTMLElement[] { 37 | return Array.from(el.parentNode!.querySelectorAll(`.${rowClass}`)) 38 | } -------------------------------------------------------------------------------- /src/utils/createFlagManager.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 给mark对象使用,用来创建管理flag的对象 3 | * @author 韦胜健 4 | * @date 2020/11/27 11:38 5 | */ 6 | import {UnwrapRef} from "plain-ui-composition"; 7 | import {reactive} from "plain-ui-composition"; 8 | 9 | export function createFlagManager() { 10 | return { 11 | state: reactive({ 12 | map: {} as { [k: string]: T } 13 | }), 14 | get(key: string) { 15 | return this.state.map[key] 16 | }, 17 | set(key: string, val: UnwrapRef) { 18 | /*if (this.state.map.hasOwnProperty(key)) { 19 | this.state.map[key] = val 20 | } else { 21 | set(this.state.map, key, val) 22 | }*/ 23 | this.state.map[key] = val 24 | }, 25 | getActiveKeys(): string[] { 26 | const keys: string[] = [] 27 | for (let key in this.state.map) { 28 | if (!!this.state.map[key]) { 29 | keys.push(key) 30 | } 31 | } 32 | return keys 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-turn-off-microphone.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/useDialog/dialog-service.scss: -------------------------------------------------------------------------------- 1 | .pl-dialog-service-edit { 2 | .pl-dialog-content { 3 | & > .pl-textarea { 4 | display: block !important; 5 | height: 100%; 6 | 7 | .pl-textarea-inner { 8 | height: 100%; 9 | } 10 | } 11 | } 12 | } 13 | 14 | @include theme { 15 | .pl-dialog-service { 16 | @include statusMixin(dialog-service) { 17 | .pl-dialog-head { 18 | background-color: rgba($value, 0.05); 19 | color: $value; 20 | /*position: relative; 21 | 22 | &:after { 23 | position: absolute; 24 | left: 0; 25 | right: 0; 26 | top: 0; 27 | height: 4px; 28 | background-color: $value; 29 | content: ''; 30 | }*/ 31 | border-top: solid 4px rgba($value, 0.85); 32 | 33 | .pl-dialog-service-head { 34 | color: $value; 35 | 36 | .pl-dialog-service-status-icon { 37 | font-size: 18px; 38 | margin-right: 4px; 39 | vertical-align: -0.25em; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-undo.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /story/pages/test/test.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 44 | 45 | 48 | -------------------------------------------------------------------------------- /src/packages/PlTree/utils/tree.utils.ts: -------------------------------------------------------------------------------- 1 | import {TreeNode} from "./type"; 2 | 3 | const basePadding = 8 4 | 5 | export const TreeUtils = { 6 | getPaddingLeft: (level: number, intent: number) => { 7 | return basePadding + (level - 1) * intent 8 | }, 9 | /** 10 | * 计算treeNode的样式 11 | * @author 韦胜健 12 | * @date 2020/11/28 9:25 13 | */ 14 | getTreeNodeStyles: (level: number, intent: number, nodeHeight: number) => { 15 | const basePadding = 8 16 | return { 17 | paddingLeft: `${TreeUtils.getPaddingLeft(level, intent)}px`, 18 | paddingRight: `${basePadding}px`, 19 | height: `${nodeHeight}px`, 20 | } 21 | }, 22 | /** 23 | * 计算tree node的class 24 | * @author 韦胜健 25 | * @date 2020/11/28 10:35 26 | */ 27 | getTreeNodeClasses: (node: TreeNode, current?: string | number) => { 28 | return [ 29 | 'pl-tree-node', 30 | { 31 | 'pl-tree-node-current': node.key == current, 32 | 'pl-tree-node-not-checkable': !node.isCheckable, 33 | } 34 | ] 35 | }, 36 | } -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-redo.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTable/plc/standard/draggier/core/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 拖拽排序实现函数的类型 3 | * @author 韦胜健 4 | * @date 2020/8/21 10:07 5 | */ 6 | import {useListDraggierNotVirtual} from "./use-list-draggier"; 7 | import {useListDraggierWithVirtual} from "./use-list-draggier.virtual"; 8 | import {PlainScroll} from "../../../../../PlScroll"; 9 | 10 | 11 | export interface UseListDraggierType { 12 | (option: { 13 | rowClass: string, // 行的class,要确保只有行所在的dom对象有这个class,其子节点是没有这个class的 14 | onChange: (start: number, end: number) => void | Promise, // 拖拽导致排序变化动作 15 | virtual?: boolean, // 是否为虚拟滚动 16 | getScroll: () => PlainScroll, 17 | }): { 18 | handler: { 19 | mousedown: (e: MouseEvent) => void, 20 | } 21 | } 22 | } 23 | 24 | export const useListDraggier: UseListDraggierType = (option) => { 25 | if (option.virtual) { 26 | return useListDraggierWithVirtual(option) 27 | } else { 28 | return useListDraggierNotVirtual(option) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-date.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlColorButton/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, useRefs} from 'plain-ui-composition' 2 | import './color-button.scss' 3 | // @ts-ignore 4 | import opacityPng from './opacity.png' 5 | 6 | export const PlColorButton = designComponent({ 7 | name: 'pl-color-button', 8 | props: { 9 | color: {type: String} 10 | }, 11 | emits: { 12 | onClick: (e: MouseEvent) => true, 13 | }, 14 | inheritPropsType: HTMLDivElement, 15 | setup({props, event: {emit}}) { 16 | 17 | const {refs, onRef} = useRefs({ 18 | el: HTMLDivElement, 19 | }) 20 | 21 | return { 22 | refer: { 23 | refs, 24 | }, 25 | render: () => ( 26 |
27 |
28 |
29 |
30 |
31 | ) 32 | } 33 | }, 34 | }) 35 | 36 | export default PlColorButton 37 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-setting.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlProgressBar/progress-bar.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-progress-bar { 3 | display: inline-flex; 4 | align-items: center; 5 | vertical-align: middle; 6 | 7 | .pl-progress-bar-content { 8 | display: inline-block; 9 | width: 50px; 10 | text-align: left; 11 | font-size: 14px; 12 | padding: 0 6px; 13 | 14 | .pl-icon { 15 | vertical-align: -0.1em; 16 | } 17 | } 18 | 19 | .pl-progress-bar-outer { 20 | display: inline-flex; 21 | align-items: center; 22 | overflow: hidden; 23 | 24 | .pl-progress-bar-inner { 25 | height: 100%; 26 | display: inline-flex; 27 | align-items: center; 28 | justify-content: flex-end; 29 | 30 | transition: all $transition 300ms; 31 | 32 | .pl-progress-bar-content { 33 | text-align: right; 34 | 35 | span { 36 | color: white; 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/packages/PlTree/utils/type.ts: -------------------------------------------------------------------------------- 1 | import {TreeDropType, TreeNodeCheckStatus} from "./tree-constant"; 2 | import {PlainObject} from "plain-utils/utils/event"; 3 | import {VueNode} from "plain-ui-composition"; 4 | 5 | export type TreeNode = { 6 | key: string, 7 | data: PlainObject, 8 | level: number, 9 | parentRef: () => TreeNode | null, 10 | selfRef: () => TreeNode, 11 | 12 | index: number, 13 | empty: boolean, 14 | 15 | readonly childrenData?: PlainObject[] 16 | readonly label?: string, 17 | children?: TreeNode[], 18 | readonly checkStatus: TreeNodeCheckStatus, 19 | 20 | expand: boolean, 21 | check: boolean, 22 | loading: boolean, 23 | loaded: boolean, 24 | 25 | readonly isCheckable: boolean, 26 | readonly isLeaf: boolean, 27 | readonly isVisible: boolean, 28 | } 29 | 30 | export namespace TreePropsType { 31 | export interface renderContent {(data: { node: TreeNode, index: number }): VueNode} 32 | 33 | export interface nodeIcon {(node: TreeNode): string} 34 | 35 | export interface allowDrag {(node: TreeNode): boolean} 36 | 37 | export interface allowDrop {(startNode: TreeNode, moveNode: TreeNode, dropType: TreeDropType): boolean} 38 | } 39 | -------------------------------------------------------------------------------- /story/pages/table-pro/format-row.tsx: -------------------------------------------------------------------------------- 1 | import {designPage} from "plain-ui-composition"; 2 | 3 | import useTableOption from "../../init/useTableOption"; 4 | import {PlcInput, PlcTextarea, PlTablePro} from "../../../src"; 5 | import {DemoRow} from "../../components/DemoRow"; 6 | 7 | export const demo1 = designPage(() => { 8 | 9 | const provinceOption = useTableOption({ 10 | url: '/address', 11 | filterParam: {queries: [{field: 'deep', value: '0', operator: '='}]}, 12 | defaultNewRow: {deep: 0,}, 13 | showRows: 5, 14 | hooks: { 15 | onFormatRow: row => { 16 | row.formatField = `_${row.code}` 17 | } 18 | }, 19 | }) 20 | 21 | return () => <> 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | }) 34 | -------------------------------------------------------------------------------- /src/packages/PlList/list.tsx: -------------------------------------------------------------------------------- 1 | import './list.scss' 2 | import {designComponent} from "plain-ui-composition"; 3 | import {TransitionGroup} from 'vue' 4 | 5 | export const PlList = designComponent({ 6 | name: 'pl-list', 7 | props: { 8 | direction: { //item入场出场动画 'left', 'right', 'top', 'bottom', 'left-top', 'top-left', 'right-top', 'top-right', 'left-bottom', 'bottom-left', 'right-bottom', 'bottom-right' 9 | type: String, 10 | default: 'bottom-right', 11 | }, 12 | tag: {type: String, default: 'div'}, 13 | disabled: {type: Boolean}, 14 | }, 15 | slots: ['default'], 16 | setup({props, slots}) { 17 | return { 18 | render: () => { 19 | const Component = (props.disabled ? props.tag : TransitionGroup) as any 20 | return ( 21 | 26 | {slots.default()} 27 | 28 | ) 29 | } 30 | } 31 | } 32 | }) 33 | -------------------------------------------------------------------------------- /src/packages/useLoading/full/index.tsx: -------------------------------------------------------------------------------- 1 | import {createServiceWithoutContext, createUseService} from "../../PlRoot/registryRootService"; 2 | import {createDefaultManager} from "../../PlRoot/createDefaultManager"; 3 | import Service from './Service' 4 | 5 | export interface LoadingMaskServiceOption { 6 | message?: string, 7 | loadingType?: string, 8 | background?: string, 9 | unlock?: boolean, 10 | } 11 | 12 | export interface LoadingMaskServiceFormatOption extends LoadingMaskServiceOption { 13 | close: () => void 14 | } 15 | 16 | export const useLoadingMask = createUseService({ 17 | name: 'loading', 18 | optionsCallName:'$loadingMask', 19 | managerComponent: createDefaultManager('pl-loading-mask-manager', Service), 20 | createService: (getManager) => { 21 | return (option: LoadingMaskServiceOption): LoadingMaskServiceFormatOption => { 22 | option = option || {}; 23 | getManager().then(manager => manager.service(option as LoadingMaskServiceFormatOption)); 24 | return option as LoadingMaskServiceFormatOption 25 | } 26 | } 27 | }, 28 | ) 29 | 30 | export const $$loadingMask = createServiceWithoutContext(useLoadingMask) 31 | -------------------------------------------------------------------------------- /src/packages/PlTable/plc/edit/plc-color-picker.tsx: -------------------------------------------------------------------------------- 1 | import PlColorButton from "../../../PlColorButton"; 2 | import PlColorPicker from "../../../PlColorPicker"; 3 | 4 | import {designComponent} from "plain-ui-composition"; 5 | import {PlcEmitsOptions, PlcPropsOptions} from "../utils/plc.utils"; 6 | import {PlcScopeSlotsOptions} from "../utils/plc.scope-slots"; 7 | import {useExternalPlc} from "../core/useExternalPlc"; 8 | 9 | export default designComponent({ 10 | name: 'plc-color-picker', 11 | props: { 12 | ...PlcPropsOptions 13 | }, 14 | scopeSlots: PlcScopeSlotsOptions, 15 | emits: PlcEmitsOptions, 16 | setup({props, slots, scopeSlots, event}) { 17 | return useExternalPlc({ 18 | props, scopeSlots, event, slots, defaultScopeSlots: { 19 | normal: ({row, plc}) => { 20 | return !!plc.props.field && <> 21 | 22 | {row[plc.props.field]} 23 | 24 | }, 25 | edit: ({row, plc}) => !plc.props.field ? null : 26 | } 27 | }) 28 | }, 29 | }) 30 | -------------------------------------------------------------------------------- /src/packages/PlFilter/editor/FilterTextContains.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, PropType, reactive, useModel} from "plain-ui-composition"; 2 | 3 | import PlInput from "../../PlInput"; 4 | 5 | export const FilterTextContains = designComponent({ 6 | props: { 7 | modelValue: {type: Array as PropType}, 8 | }, 9 | emits: { 10 | onUpdateModelValue: (val?: any[]) => true, 11 | onEnter: () => true, 12 | }, 13 | setup({props, event: {emit}}) { 14 | 15 | const model = useModel(() => props.modelValue, emit.onUpdateModelValue, { 16 | onChange: val => { 17 | state.text = (val || []).join(',') 18 | } 19 | }) 20 | 21 | const state = reactive({ 22 | text: (model.value || []).join(',') 23 | }) 24 | 25 | const handler = { 26 | onChange: () => { 27 | if (state.text === (model.value || []).join(',')) { 28 | return 29 | } else { 30 | model.value = state.text.split(/[,,]/g).filter(i => !!(i.trim())) 31 | } 32 | } 33 | } 34 | 35 | return () => 36 | }, 37 | }) 38 | -------------------------------------------------------------------------------- /src/packages/PlProgressCircle/progress-circle.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-progress-circle { 3 | position: relative; 4 | display: inline-block; 5 | vertical-align: middle; 6 | border-radius: 1000px; 7 | 8 | & > svg > path { 9 | transform-origin: center center; 10 | } 11 | 12 | .pl-progress-circle-label { 13 | height: 100%; 14 | width: 100%; 15 | position: absolute; 16 | top: 0; 17 | left: 0; 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | 22 | .pl-icon { 23 | font-size: 24px; 24 | } 25 | } 26 | 27 | @keyframes path-animate { 28 | from { 29 | transform: rotate(0deg); 30 | } 31 | to { 32 | transform: rotate(360deg); 33 | } 34 | } 35 | 36 | &.pl-progress-circle-loading { 37 | & > svg { 38 | animation: path-animate 15000ms linear infinite; 39 | 40 | & > path { 41 | animation: path-animate 1500ms linear infinite; 42 | } 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/typescript/recommended' 10 | ], 11 | parserOptions: { 12 | ecmaVersion: 2020 13 | }, 14 | rules: { 15 | 'no-console': 'off', 16 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 17 | '@typescript-eslint/no-non-null-assertion': 'off', 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | '@typescript-eslint/no-use-before-define': 'off', 20 | '@typescript-eslint/member-delimiter-style': 'off', 21 | 'no-extra-boolean-cast': 'off', 22 | '@typescript-eslint/no-unused-vars': 'off', 23 | '@typescript-eslint/no-var-requires': 'off', 24 | '@typescript-eslint/ban-ts-ignore': 'off', 25 | '@typescript-eslint/explicit-module-boundary-types': 'off', 26 | '@typescript-eslint/prefer-as-const': 'off', 27 | '@typescript-eslint/ban-ts-comment': 'off', 28 | '@typescript-eslint/no-empty-function': 'off', 29 | '@typescript-eslint/no-namespace': 'off', 30 | 'prefer-const': 'off', 31 | 'no-case-declarations': 'off', 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/packages/PlcTextarea/PlTextareaDialog.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, useModel} from "plain-ui-composition"; 2 | 3 | import {EditProps, useEdit} from "../../use/useEdit"; 4 | import PlInput from "../PlInput"; 5 | import useDialog from "../useDialog"; 6 | 7 | export const PlTextareDialog = designComponent({ 8 | name: 'pl-textarea-dialog', 9 | props: { 10 | ...EditProps, 11 | modelValue: {type: [String, Number] as any}, 12 | }, 13 | emits: { 14 | onUpdateModelValue: (val?: any) => true, 15 | }, 16 | setup({props, event: {emit}}) { 17 | 18 | const $dialog = useDialog() 19 | const {editComputed} = useEdit() 20 | 21 | const model = useModel(() => props.modelValue, emit.onUpdateModelValue) 22 | 23 | const onClick = () => { 24 | if (!editComputed.value.editable) {return} 25 | $dialog({ 26 | editType: 'textarea', 27 | editValue: model.value, 28 | confirmButton: true, 29 | cancelButton: true, 30 | onConfirm: (val) => { 31 | model.value = val 32 | } 33 | }) 34 | } 35 | 36 | return () => 37 | }, 38 | }) 39 | -------------------------------------------------------------------------------- /story/pages/data/mock.js: -------------------------------------------------------------------------------- 1 | /* 2 | const fs = require('fs') 3 | const path = require('path') 4 | const mock = require('mockjs').mock 5 | 6 | function generate() { 7 | [ 8 | {file: 'data.json', num: 2000}, 9 | {file: 'data-1.json', num: 50}, 10 | {file: 'data-2.json', num: 200}, 11 | ].forEach((item) => { 12 | fs.writeFileSync(path.resolve(__dirname, `./${item.file}`), JSON.stringify( 13 | (mock({ 14 | [`array|${item.num}`]: [ 15 | { 16 | "id|+1": 0, 17 | color: '@color', 18 | name: '@first', 19 | date: '@date', 20 | "star|0-10": 5, 21 | "flag": () => Math.random() > 0.5 ? 'Y' : 'N', 22 | "size|40-80": 60, 23 | addr: '@county(true)', 24 | url: '@url', 25 | domain: '@domain', 26 | protocol: '@protocol', 27 | email: '@email', 28 | ip: '@ip', 29 | } 30 | ] 31 | })).array, 32 | null, 33 | 2, 34 | )) 35 | }) 36 | } 37 | 38 | generate()*/ 39 | -------------------------------------------------------------------------------- /src/packages/PlIcon/icons/el-icon-code.json: -------------------------------------------------------------------------------- 1 | [""] -------------------------------------------------------------------------------- /src/packages/PlTable/plc/standard/plc-index.tsx: -------------------------------------------------------------------------------- 1 | 2 | import {designComponent} from "plain-ui-composition"; 3 | import {createPlcPropOptions, PlcEmitsOptions} from "../utils/plc.utils"; 4 | import {PlcScopeSlotsOptions} from "../utils/plc.scope-slots"; 5 | import {useExternalPlc} from "../core/useExternalPlc"; 6 | 7 | export default designComponent({ 8 | name: 'plc-index', 9 | props: { 10 | ...createPlcPropOptions({ 11 | autoFixedLeft: true, 12 | order: -9995, 13 | width: 45, 14 | align: 'center', 15 | noPadding: true, 16 | hideInForm: true, 17 | }), 18 | summaryText: {type: String, default: '合计'}, 19 | start: {type: Number, default: 0}, 20 | }, 21 | scopeSlots: { 22 | ...PlcScopeSlotsOptions, 23 | }, 24 | emits: { 25 | ...PlcEmitsOptions, 26 | }, 27 | setup({props, slots, scopeSlots, event}) { 28 | return useExternalPlc({ 29 | props, scopeSlots, event, slots, defaultScopeSlots: { 30 | head: () => '#', 31 | normal: ({node, plc}) => (plc.props as any).start + node.index + 1, 32 | summary: () => {props.summaryText}, 33 | } 34 | }) 35 | }, 36 | }) 37 | -------------------------------------------------------------------------------- /src/packages/PlTable/plc/utils/plc.scope-slots.tsx: -------------------------------------------------------------------------------- 1 | import {TableRenderScope, tPlcType} from "./plc.type"; 2 | import {VueNode} from "plain-ui-composition"; 3 | 4 | export type PlcRenderFunction = (scope: TableRenderScope) => VueNode 5 | export type PlcPropsHead = (scope: { plc: tPlcType }) => VueNode 6 | export type PlcPropsDefault = PlcRenderFunction 7 | export type PlcPropsSummary = PlcRenderFunction 8 | export type PlcPropsEdit = PlcRenderFunction 9 | export type PlcPropsForm = PlcRenderFunction 10 | 11 | export type ScopeSlotsType any>> = { [k in keyof ScopeSlots]: ((scope: Parameters[0], defaultNode?: VueNode) => VueNode) & { isExist: () => boolean } } 12 | 13 | export const PlcScopeSlotsOptions = { 14 | head: {} as PlcPropsHead, // 列标题渲染函数 15 | normal: {} as PlcPropsDefault, // 列内容默认渲染函数 16 | summary: {} as PlcPropsSummary, // 列内容在合计行上的渲染函数 17 | edit: {} as PlcPropsEdit, // 列内容在编辑状态下的渲染函数 18 | form: {} as PlcPropsForm, // 表单编辑时渲染的内容 19 | } 20 | 21 | export type tPlcScopeSlots = ScopeSlotsType 22 | 23 | export type tPlcSlots = Record VueNode) & { isExist: () => boolean }> 24 | -------------------------------------------------------------------------------- /src/utils/createAnimate.ts: -------------------------------------------------------------------------------- 1 | export function createAnimate( 2 | { 3 | initValue, 4 | time, 5 | action, 6 | }: { 7 | initValue: () => number, 8 | time: number, 9 | action: (val: number) => void, 10 | }) { 11 | 12 | let cancel = null as null | number 13 | 14 | return { 15 | start: (percent: number, done?: () => void) => { 16 | if (cancel != null) { 17 | cancelAnimationFrame(cancel) 18 | } 19 | let startTime = Date.now() 20 | 21 | let n = initValue() 22 | let k = (percent - n) / time 23 | 24 | const run = () => { 25 | let nowTime = Date.now() 26 | let deltaTime = nowTime - startTime 27 | 28 | if (deltaTime > time) { 29 | cancel = null 30 | action(percent) 31 | !!done && done() 32 | return 33 | } 34 | action(Number((deltaTime * k + n).toFixed(2))) 35 | cancel = requestAnimationFrame(run) 36 | } 37 | run() 38 | }, 39 | stop: () => { 40 | if (cancel != null) { 41 | cancelAnimationFrame(cancel) 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/packages/createUseTableOption/use/use.cache.utils.tsx: -------------------------------------------------------------------------------- 1 | import {tPlc, tPlcType} from "../../PlTable/plc/utils/plc.type"; 2 | 3 | export interface iTableOptionCacheItemData { 4 | id: number, 5 | title: string, 6 | time: string, 7 | data: Record, 8 | } 9 | 10 | export interface iTableOptionCacheData { 11 | tableId: string, 12 | activeId: number | undefined, 13 | data: iTableOptionCacheItemData[], 14 | } 15 | 16 | export interface iTableOptionApplyCacheParam { 17 | plcList: tPlc[], 18 | cacheData: CacheData | undefined 19 | sourceList: tPlcType[], 20 | } 21 | 22 | export interface iTableOptionGetCacheParam { 23 | plcList: tPlc[], 24 | sourceList: tPlcType[], 25 | } 26 | 27 | export interface iTableOptionCacheRegistryConfig { 28 | cacheKey: string, 29 | applyCache: (param: iTableOptionApplyCacheParam) => void, 30 | getCache: (param: iTableOptionGetCacheParam) => CacheData, 31 | } 32 | 33 | export const getTableId = (plcTypeList: tPlcType[]): string => { 34 | return plcTypeList.map(i => { 35 | if (i.group) { 36 | return `${i.props.title || '#'}-${getTableId(i.children)}` 37 | } else { 38 | return `${i.props.title || '#'}-${i.props.field || '@'}` 39 | } 40 | }).join('_') 41 | } 42 | -------------------------------------------------------------------------------- /src/packages/PlTabs/header/horizontal/tabs-header-text.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-tabs-header.pl-tabs-header-horizontal.pl-tabs-header-type-text { 3 | 4 | .pl-tabs-header-item { 5 | line-height: 45px; 6 | 7 | & + .pl-tabs-header-item { 8 | margin-left: 32px; 9 | } 10 | 11 | &.pl-tabs-header-item-active, &:hover { 12 | color: $colorPrimary; 13 | } 14 | } 15 | 16 | .pl-tabs-header-list { 17 | position: relative; 18 | 19 | .pl-tabs-header-horizontal-text-indicator-container { 20 | background-color: $disabled; 21 | position: absolute; 22 | left: 0; 23 | right: 0; 24 | height: 2px; 25 | 26 | .pl-tabs-header-horizontal-text-indicator { 27 | position: absolute; 28 | width: 0; 29 | left: 0; 30 | height: 100%; 31 | background-color: $colorPrimary; 32 | display: block; 33 | transition: $transition 150ms all; 34 | } 35 | } 36 | } 37 | 38 | &.pl-tabs-header-pos-top { 39 | .pl-tabs-header-horizontal-text-indicator-container { 40 | bottom: 0; 41 | } 42 | } 43 | 44 | &.pl-tabs-header-pos-bottom { 45 | .pl-tabs-header-horizontal-text-indicator-container { 46 | top: 0; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/packages/PlDropdownGroup/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent, useClasses, useRefs} from "plain-ui-composition"; 2 | 3 | export const PlDropdownGroup = designComponent({ 4 | name: 'pl-dropdown-group', 5 | props: { 6 | title: {type: String} 7 | }, 8 | slots: ['default', 'head'], 9 | inheritPropsType: HTMLDivElement, 10 | setup({props, slots}) { 11 | 12 | const {refs, onRef} = useRefs({el: HTMLDivElement}) 13 | 14 | const classes = useClasses(() => [ 15 | 'pl-dropdown-group', 16 | {'pl-dropdown-no-title': !slots.head.isExist() && !props.title} 17 | ]) 18 | 19 | return { 20 | refer: { 21 | refs, 22 | }, 23 | render: () => ( 24 |
25 | {slots.head.isExist() || props.title && ( 26 |
27 | {slots.head(props.title)} 28 |
29 | )} 30 |
31 | {slots.default()} 32 |
33 |
34 | ) 35 | } 36 | }, 37 | }) 38 | 39 | export default PlDropdownGroup 40 | -------------------------------------------------------------------------------- /src/packages/PlcObject/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition"; 2 | import PlObject, {PlObjectPropsOption} from "../PlObject"; 3 | import {PlcEmitsOptions, PlcPropsOptions} from "../PlTable/plc/utils/plc.utils"; 4 | import {PlcScopeSlotsOptions} from "../PlTable/plc/utils/plc.scope-slots"; 5 | import {useExternalPlc} from "../PlTable/plc/core/useExternalPlc"; 6 | 7 | 8 | export const PlcObject = designComponent({ 9 | name: 'plc-object', 10 | props: { 11 | ...PlcPropsOptions, 12 | ...PlObjectPropsOption, 13 | }, 14 | scopeSlots: PlcScopeSlotsOptions, 15 | emits: PlcEmitsOptions, 16 | setup({props, slots, scopeSlots, event}) { 17 | return useExternalPlc({ 18 | props, scopeSlots, slots, event, defaultScopeSlots: { 19 | edit: ({row, plc}) => !plc.props.field ? null : 20 | { 22 | prev[key] = (props as any)[key] 23 | return prev 24 | }, {} as Record)} 25 | showKey={plc.props.field} 26 | row={row} 27 | /> 28 | } 29 | }) 30 | }, 31 | }) 32 | 33 | export default PlcObject 34 | -------------------------------------------------------------------------------- /src/utils/findReactElement.tsx: -------------------------------------------------------------------------------- 1 | import {VueNode} from "plain-ui-composition"; 2 | import {isVNode} from 'vue' 3 | 4 | export function findReactElement(node: VueNode, isMatch: (node: VueNode) => boolean): VueNode[] | null { 5 | 6 | if (node == null) {return null} 7 | const type = typeof node 8 | switch (type) { 9 | case "number": 10 | case "string": 11 | case "boolean": 12 | return null 13 | } 14 | 15 | if (Array.isArray(node) && node.length > 0) { 16 | const ret: VueNode[] = [] 17 | node.forEach(n => { 18 | const findList = findReactElement(n, isMatch) 19 | if (!!findList && findList.length > 0) { 20 | ret.push(...findList) 21 | } 22 | }) 23 | return ret 24 | } 25 | 26 | if (isVNode(node)) { 27 | if (isMatch(node)) { 28 | return [node] 29 | } 30 | if (node.children && Array.isArray(node.children)) { 31 | const ret: VueNode[] = [] 32 | node.children.forEach(n => { 33 | const findList = findReactElement(n, isMatch) 34 | if (!!findList && findList.length > 0) { 35 | ret.push(...findList) 36 | } 37 | }) 38 | return ret 39 | } 40 | } 41 | 42 | return null 43 | } 44 | -------------------------------------------------------------------------------- /story/pages/data/mock.database.js: -------------------------------------------------------------------------------- 1 | /* 2 | const fs = require('fs') 3 | const path = require('path') 4 | const mock = require('mockjs').mock 5 | 6 | const createGeneratoe = (options) => { 7 | const {length} = options 8 | return () => { 9 | return options[Math.floor(Math.random() * length)] 10 | } 11 | } 12 | 13 | const nextFlag = createGeneratoe(['Y', 'N']) 14 | const nextSelect = createGeneratoe(['potential', 'store', 'consumer']) 15 | 16 | function generate() { 17 | const data = (mock({ 18 | [`array|${100}`]: [ 19 | { 20 | id: '@guid', 21 | created_at: '@datetime', 22 | created_by: '@first', 23 | updated_at: '@datetime', 24 | updated_by: '@first', 25 | normal_text: '@first', 26 | long_text: '@paragraph', 27 | 'number_val|1-100': 100, 28 | flag: nextFlag, 29 | select_val: nextSelect, 30 | color_val: '@color', 31 | date_val: '@datetime', 32 | time_val: '@time', 33 | parent_id: '', 34 | image_id: '', 35 | } 36 | ] 37 | })).array; 38 | 39 | fs.writeFileSync(path.resolve(__dirname, `./demo.json`), JSON.stringify(data, null, 2,)) 40 | } 41 | 42 | generate() 43 | */ 44 | -------------------------------------------------------------------------------- /src/packages/PlInputGroup/input-group.scss: -------------------------------------------------------------------------------- 1 | .pl-input-group { 2 | display: inline-block; 3 | white-space: nowrap; 4 | 5 | & > * { 6 | display: inline-block; 7 | 8 | &.pl-input-group.pl-input-group-block { 9 | display: inline-flex; 10 | } 11 | } 12 | 13 | &.pl-input-group-block { 14 | width: 100%; 15 | display: flex; 16 | align-items: center; 17 | flex-wrap: nowrap; 18 | } 19 | 20 | & > *:not(:first-child) { 21 | border-top-left-radius: 0 !important; 22 | border-bottom-left-radius: 0 !important; 23 | 24 | input, .pl-input-inner { 25 | border-top-left-radius: 0 !important; 26 | border-bottom-left-radius: 0 !important; 27 | } 28 | } 29 | 30 | & > *:not(:last-child) { 31 | border-top-right-radius: 0 !important; 32 | border-bottom-right-radius: 0 !important; 33 | 34 | input, .pl-input-inner { 35 | border-top-right-radius: 0 !important; 36 | border-bottom-right-radius: 0 !important; 37 | } 38 | } 39 | 40 | & > .pl-button { 41 | position: relative; 42 | z-index: 2; 43 | } 44 | 45 | & > *, & > * input { 46 | &:hover, &:focus, &.pl-input-focus { 47 | position: relative; 48 | z-index: 1; 49 | } 50 | } 51 | 52 | @for $i from 2 through 10 { 53 | & > *:nth-child(#{$i}) { 54 | margin-left: -#{$i - 1}px; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/packages/PlBadge/badge.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-badge { 3 | @include public-style; 4 | display: inline-block; 5 | vertical-align: baseline; 6 | position: relative; 7 | 8 | .pl-badge-content { 9 | position: absolute; 10 | font-size: 12px; 11 | padding: 2px 4px; 12 | border: solid 1px white; 13 | 14 | @include statusMixin(badge-content) { 15 | background-color: $value; 16 | border-radius: 100px; 17 | color: white; 18 | } 19 | 20 | &.pl-badge-content-top { 21 | top: 0; 22 | 23 | &.pl-badge-content-start { 24 | transform: translate(-50%, -50%); 25 | } 26 | 27 | &.pl-badge-content-end { 28 | transform: translate(50%, -50%); 29 | } 30 | } 31 | 32 | &.pl-badge-content-bottom { 33 | bottom: 0; 34 | 35 | &.pl-badge-content-start { 36 | transform: translate(-50%, 50%); 37 | } 38 | 39 | &.pl-badge-content-end { 40 | transform: translate(50%, 50%); 41 | } 42 | } 43 | 44 | &.pl-badge-content-start { 45 | left: 0; 46 | } 47 | 48 | &.pl-badge-content-end { 49 | right: 0; 50 | } 51 | 52 | &.pl-badge-content-dot { 53 | height: 12px; 54 | width: 12px; 55 | padding: 0; 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/packages/PlTime/panel/time-base-column.scss: -------------------------------------------------------------------------------- 1 | @import "./time.public"; 2 | 3 | @include theme { 4 | .pl-time-base-column { 5 | display: inline-block; 6 | height: 7*$time-size; 7 | width: 40px; 8 | border-radius: 2px; 9 | 10 | .pl-time-base-column-list { 11 | margin: 0; 12 | padding: 0; 13 | list-style: none; 14 | position: relative; 15 | 16 | .pl-time-base-column-item { 17 | font-size: 12px; 18 | height: $time-size; 19 | line-height: $time-size; 20 | transition: all 300ms $transition; 21 | text-align: center; 22 | 23 | &.pl-time-base-column-option-item { 24 | cursor: pointer; 25 | 26 | &:hover { 27 | background-color: rgba($colorInfo, 0.1); 28 | color: $ihc; 29 | } 30 | } 31 | 32 | &.pl-time-base-column-item-disabled { 33 | color: $disabledText; 34 | cursor: not-allowed; 35 | 36 | &:hover { 37 | color: $disabledText; 38 | background-color: transparent; 39 | } 40 | } 41 | 42 | &.pl-time-base-column-item-current { 43 | background-color: rgba($colorPrimary, 0.1); 44 | color: $colorPrimary; 45 | 46 | &:hover { 47 | color: $colorPrimary; 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/packages/PlColorPicker/sub/color-sv-panel.scss: -------------------------------------------------------------------------------- 1 | @include theme { 2 | .pl-color-sv-panel { 3 | position: relative; 4 | box-shadow: 0 0px 4px 0 rgba(0, 0, 0, 0.4); 5 | cursor: pointer; 6 | display: inline-block; 7 | 8 | &:before, &:after, & span { 9 | pointer-events: none; 10 | } 11 | 12 | &, &:before, &:after { 13 | border-radius: 2px; 14 | } 15 | 16 | &:before, &:after { 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | right: 0; 21 | bottom: 0; 22 | content: ''; 23 | } 24 | 25 | &:before { 26 | background: linear-gradient(to right, white, rgba(255, 255, 255, 0)); 27 | } 28 | 29 | &:after { 30 | background: linear-gradient(to top, black, rgba(255, 255, 255, 0)); 31 | } 32 | 33 | .pl-color-sv-thumb { 34 | display: inline-block; 35 | position: absolute; 36 | width: 1px; 37 | height: 1px; 38 | left: 0; 39 | top: 0; 40 | z-index: 1; 41 | 42 | &:after { 43 | display: inline-block; 44 | width: 10px; 45 | height: 10px; 46 | border: solid 1px #999; 47 | border-radius: 10px; 48 | position: absolute; 49 | top: -5px; 50 | left: -5px; 51 | content: ''; 52 | box-sizing: border-box; 53 | background-color: white; 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/packages/PlCheckboxInner/index.tsx: -------------------------------------------------------------------------------- 1 | import {designComponent} from "plain-ui-composition" 2 | import {useClasses} from "plain-ui-composition"; 3 | import {SVGAttributes} from 'vue' 4 | 5 | import {CheckboxStatus} from "../../utils/constant"; 6 | import './checkbox-inner.scss' 7 | 8 | export const PlCheckboxInner = designComponent({ 9 | name: 'pl-checkbox-inner', 10 | props: { 11 | disabled: {type: Boolean}, 12 | checkStatus: {type: String}, 13 | }, 14 | inheritPropsType: {} as SVGAttributes, 15 | setup({props}) { 16 | 17 | const classes = useClasses(() => [ 18 | 'pl-checkbox-inner', 19 | `pl-checkbox-inner-status-${props.checkStatus}`, 20 | { 21 | 'pl-checkbox-inner-disabled': props.disabled, 22 | } 23 | ]) 24 | 25 | return { 26 | render: () => ( 27 | 28 | {props.checkStatus === CheckboxStatus.check && } 29 | {props.checkStatus === CheckboxStatus.minus && } 30 | 31 | ) 32 | } 33 | }, 34 | }) 35 | 36 | export default PlCheckboxInner 37 | -------------------------------------------------------------------------------- /src/packages/PlRoot/createDefaultService.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 创建一个默认的root service组件 3 | * 这个组件最后返回的refer,必须含有isShow、isOpen、service三个属性。 4 | * isShow:当前是否已经显示,因为存在过渡动画,所以如果值为true,但是此时在页面可能没有完全显示。值为false,可能在页面上没有完全隐藏; 5 | * isOpen:当前是否已经在页面上完全打开或者消失。值为true,表示当前已经完全显示,但是此时isShow可能为false。因为隐藏过渡动画没有结束的时候就是这种情况、同理isOpen为true的时候也是这样。 6 | * 只有当isShow以及isOpen都是false的情况下,这个service才是处于闲置可以服用的状态。 7 | * 8 | * @author 韦胜健 9 | * @date 2020/11/26 9:24 10 | */ 11 | import {designComponent, VueNode} from "plain-ui-composition"; 12 | 13 | export function createDefaultService