├── .github └── workflows │ ├── doc-build.yml │ ├── go.yml │ ├── vuetifyjs-build.yml │ └── vuetifyjs-test.yml ├── .gitignore ├── LICENSE ├── exchange ├── container.go ├── csv.go ├── dig │ └── ecvariants │ │ └── main.go ├── example_test.go ├── exporter.go ├── exporter_test.go ├── importer.go ├── importer_test.go ├── meta.go ├── options.go ├── setup_test.go └── utils.go ├── go.mod ├── go.sum ├── i18n ├── dyna.go ├── i18n-transfer │ ├── README.md │ ├── csv │ │ ├── csv_to_translations_map.go │ │ └── translations_map_to_csv.go │ ├── main.go │ ├── parser │ │ ├── export_to_translation_map.go │ │ ├── import_from_translation_map.go │ │ ├── parse_dir.go │ │ ├── utils.go │ │ └── visitor.go │ └── test │ │ ├── mock │ │ ├── main.go │ │ ├── messages │ │ │ ├── message.go │ │ │ └── phone.go │ │ ├── out_messages │ │ │ └── message.go │ │ └── test_import.csv │ │ └── transfer_test.go ├── i18n.go └── i18n_test.go ├── login ├── assets.go ├── assets │ ├── style.css │ └── zxcvbn.js ├── buildcss.sh ├── builder.go ├── claims.go ├── example │ └── main.go ├── flash.go ├── helpers.go ├── helpers_test.go ├── messages.go ├── middleware.go ├── oauth_user.go ├── primary_field.go ├── session_secure.go ├── tailwind.config.js ├── user_pass.go ├── utils.go ├── view_common.go ├── view_helper.go └── views.go ├── oss ├── .gitignore ├── aliyun │ ├── README.md │ ├── aliyun.go │ └── aliyun_test.go ├── filesystem │ ├── filesystem.go │ └── filesystem_test.go ├── oss.go ├── qiniu │ ├── README.md │ ├── qiniu.go │ └── qiniu_test.go ├── s3 │ ├── README.md │ ├── s3.go │ └── s3_test.go ├── tencent │ ├── tencent.go │ ├── tencent_test.go │ └── util.go └── tests │ ├── sample.txt │ └── tests.go ├── perm ├── builder.go ├── db_policy.go ├── integration_test.go ├── matcher.go ├── policy.go └── verifier.go ├── sitemap ├── README.md ├── http.go ├── ping.go ├── robots.go ├── robots_test.go ├── sitemap.go ├── sitemap_test.go └── xml.go └── ui ├── build_package_json.sh ├── cropper ├── cropper.go ├── cropperjs │ ├── .gitignore │ ├── README.md │ ├── dist │ │ ├── cropperjs.css │ │ └── cropperjs.umd.cjs │ ├── index.html │ ├── package.json │ ├── pnpm-lock.yaml │ ├── public │ │ └── favicon.ico │ ├── src │ │ ├── demo │ │ │ ├── App.vue │ │ │ ├── components │ │ │ │ └── CropperExample.vue │ │ │ ├── main.ts │ │ │ └── vite-env.d.ts │ │ └── lib │ │ │ ├── Cropper.vue │ │ │ ├── main.ts │ │ │ └── vite-env.d.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts └── embed.go ├── fileicons ├── embed.go └── icons │ ├── ai.svg │ ├── avi.svg │ ├── css.svg │ ├── csv.svg │ ├── dbf.svg │ ├── doc.svg │ ├── dwg.svg │ ├── exe.svg │ ├── file.svg │ ├── fla.svg │ ├── html.svg │ ├── iso.svg │ ├── js.svg │ ├── json.svg │ ├── mp3.svg │ ├── mp4.svg │ ├── pdf.svg │ ├── ppt.svg │ ├── psd.svg │ ├── rtf.svg │ ├── svg.svg │ ├── txt.svg │ ├── xls.svg │ ├── xml.svg │ └── zip.svg ├── redactor ├── embed.go ├── redactor.go └── redactorjs │ ├── .gitignore │ ├── README.md │ ├── dist │ ├── redactor.css │ └── redactorjs.umd.cjs │ ├── index.html │ ├── jsconfig.json │ ├── package.json │ ├── pnpm-lock.yaml │ ├── public │ └── favicon.ico │ ├── src │ ├── demo │ │ ├── App.vue │ │ └── main.js │ └── lib │ │ ├── RichTextRedactor.vue │ │ ├── main.js │ │ ├── redactor.min.css │ │ └── redactor.min.js │ └── vite.config.js ├── rm_node_modules.sh ├── tiptap ├── build.sh ├── tiptap.go ├── tiptapjs.go └── tiptapjs │ ├── .gitignore │ ├── README.md │ ├── dist │ ├── tiptap.css │ └── tiptapjs.umd.cjs │ ├── index.html │ ├── package.json │ ├── pnpm-lock.yaml │ ├── public │ └── favicon.ico │ ├── src │ ├── demo │ │ ├── App.vue │ │ ├── components │ │ │ └── EditorExample.vue │ │ ├── main.ts │ │ └── vite-env.d.ts │ └── lib │ │ ├── Editor.vue │ │ ├── Icon.vue │ │ ├── icons │ │ ├── add_col_after.svg │ │ ├── add_col_before.svg │ │ ├── add_row_after.svg │ │ ├── add_row_before.svg │ │ ├── bold.svg │ │ ├── checklist.svg │ │ ├── code.svg │ │ ├── code_block.svg │ │ ├── combine_cells.svg │ │ ├── delete_col.svg │ │ ├── delete_row.svg │ │ ├── delete_table.svg │ │ ├── github.svg │ │ ├── hr.svg │ │ ├── image.svg │ │ ├── italic.svg │ │ ├── link.svg │ │ ├── mention.svg │ │ ├── ol.svg │ │ ├── paragraph.svg │ │ ├── quote.svg │ │ ├── redo.svg │ │ ├── remove.svg │ │ ├── strike.svg │ │ ├── table.svg │ │ ├── ul.svg │ │ ├── underline.svg │ │ └── undo.svg │ │ ├── main.ts │ │ ├── sass │ │ ├── editor.scss │ │ ├── main.scss │ │ ├── menubar.scss │ │ ├── menububble.scss │ │ └── variables.scss │ │ └── vite-env.d.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── update_package_json.sh ├── vuetify ├── alert-title.go ├── alert.go ├── app-bar-nav-icon.go ├── app-bar-title.go ├── app-bar.go ├── app.go ├── autocomplete.go ├── avatar.go ├── badge.go ├── banner-actions.go ├── banner-text.go ├── banner.go ├── bottom-navigation.go ├── bottom-sheet.go ├── breadcrumbs-divider.go ├── breadcrumbs-item.go ├── breadcrumbs.go ├── btn-group.go ├── btn-toggle.go ├── btn.go ├── calendar-day.go ├── calendar-header.go ├── calendar-interval-event.go ├── calendar-interval.go ├── calendar-month-day.go ├── calendar.go ├── card-actions.go ├── card-item.go ├── card-subtitle.go ├── card-text.go ├── card-title.go ├── card.go ├── carousel-item.go ├── carousel.go ├── checkbox-btn.go ├── checkbox.go ├── chip-group.go ├── chip.go ├── class-icon.go ├── code.go ├── col.go ├── color-picker.go ├── combobox.go ├── component-icon.go ├── confirm-edit.go ├── container.go ├── counter.go ├── data-iterator.go ├── data-table-footer.go ├── data-table-headers.go ├── data-table-row.go ├── data-table-rows.go ├── data-table-server.go ├── data-table-virtual.go ├── data-table.go ├── date-input.go ├── date-picker-controls.go ├── date-picker-header.go ├── date-picker-month.go ├── date-picker-months.go ├── date-picker-years.go ├── date-picker.go ├── defaults-provider.go ├── dialog-bottom-transition.go ├── dialog-top-transition.go ├── dialog-transition.go ├── dialog.go ├── divider.go ├── empty-state.go ├── expand-transition.go ├── expand-x-transition.go ├── expansion-panel-text.go ├── expansion-panel-title.go ├── expansion-panel.go ├── expansion-panels.go ├── fab-transition.go ├── fab.go ├── fade-transition.go ├── field-label.go ├── field.go ├── file-input.go ├── fix-autocomplete.go ├── fix-btn.go ├── fix-checkbox.go ├── fix-chip-group.go ├── fix-color-theme.go ├── fix-consts.go ├── fix-container.go ├── fix-file-input.go ├── fix-icon.go ├── fix-list-item.go ├── fix-option-item.go ├── fix-radio-group.go ├── fix-select.go ├── fix-slider.go ├── fix-switch.go ├── fix-table.go ├── fix-text-field.go ├── fix-textarea.go ├── fix-toolbar-title.go ├── fix-toolbar.go ├── fix-utils.go ├── footer.go ├── form.go ├── gen_vuetify.sh ├── hover.go ├── icon.go ├── img.go ├── infinite-scroll.go ├── input.go ├── item-group.go ├── item.go ├── kbd.go ├── label.go ├── layout-item.go ├── layout.go ├── lazy.go ├── ligature-icon.go ├── list-group.go ├── list-img.go ├── list-item-action.go ├── list-item-media.go ├── list-item-subtitle.go ├── list-item-title.go ├── list-item.go ├── list-subheader.go ├── list.go ├── locale-provider.go ├── main.go ├── menu.go ├── messages.go ├── navigation-drawer.go ├── no-ssr.go ├── number-input.go ├── otp-input.go ├── overlay.go ├── pagination.go ├── parallax.go ├── picker-title.go ├── picker.go ├── progress-circular.go ├── progress-linear.go ├── pull-to-refresh.go ├── radio-group.go ├── radio.go ├── range-slider.go ├── rating.go ├── responsive.go ├── row.go ├── scale-transition.go ├── scroll-x-reverse-transition.go ├── scroll-x-transition.go ├── scroll-y-reverse-transition.go ├── scroll-y-transition.go ├── select.go ├── selection-control-group.go ├── selection-control.go ├── sheet.go ├── skeleton-loader.go ├── slide-group-item.go ├── slide-group.go ├── slide-x-reverse-transition.go ├── slide-x-transition.go ├── slide-y-reverse-transition.go ├── slide-y-transition.go ├── slider.go ├── snackbar-queue.go ├── snackbar.go ├── spacer.go ├── sparkline.go ├── speed-dial.go ├── stepper-actions.go ├── stepper-header.go ├── stepper-item.go ├── stepper-vertical-actions.go ├── stepper-vertical-item.go ├── stepper-vertical.go ├── stepper-window-item.go ├── stepper-window.go ├── stepper.go ├── svg-icon.go ├── switch.go ├── system-bar.go ├── tab.go ├── table.go ├── tabs-window-item.go ├── tabs-window.go ├── tabs.go ├── text-field.go ├── textarea.go ├── theme-provider.go ├── time-picker-clock.go ├── time-picker-controls.go ├── time-picker.go ├── timeline-item.go ├── timeline.go ├── toolbar-items.go ├── toolbar-title.go ├── toolbar.go ├── tooltip.go ├── treeview-group.go ├── treeview-item.go ├── treeview.go ├── validation.go ├── virtual-scroll.go ├── window-item.go └── window.go └── vuetifyx ├── README.md ├── autocomplete-fix.go ├── autocomplete.go ├── build.sh ├── buildinAsserts └── vuetify.min.3.7.18.css ├── card.go ├── data-table.go ├── detail-info.go ├── draggable.go ├── filter.go ├── filter_test.go ├── key-info.go ├── linkage-select-remote-fix.go ├── linkage-select-remote.go ├── linkage-select.go ├── message-listener.go ├── overlay.go ├── picker.go ├── readonly-field.go ├── scroll-iframe.go ├── select-many.go ├── table-pagination.go ├── text-field.go ├── tiptap-editor.go ├── vuetifyxjs.go ├── vuetifyxjs ├── .browserslistrc ├── .editorconfig ├── .gitignore ├── .prettierrc.json ├── README.md ├── components.d.ts ├── dist │ ├── assets │ │ ├── materialdesignicons-webfont.eot │ │ ├── materialdesignicons-webfont.ttf │ │ ├── materialdesignicons-webfont.woff │ │ ├── materialdesignicons-webfont.woff2 │ │ └── vuetifyx.min.css │ └── vuetifyx.min.js ├── docs │ ├── .vitepress │ │ ├── config.ts │ │ └── theme │ │ │ ├── index.ts │ │ │ ├── myLayout.ts │ │ │ ├── register-components.ts │ │ │ ├── shared.js │ │ │ ├── theme-default │ │ │ ├── Layout.vue │ │ │ ├── NotFound.vue │ │ │ ├── components │ │ │ │ ├── VPAlgoliaSearchBox.vue │ │ │ │ ├── VPBackdrop.vue │ │ │ │ ├── VPBadge.vue │ │ │ │ ├── VPButton.vue │ │ │ │ ├── VPCarbonAds.vue │ │ │ │ ├── VPContent.vue │ │ │ │ ├── VPDoc.vue │ │ │ │ ├── VPDocAside.vue │ │ │ │ ├── VPDocAsideCarbonAds.vue │ │ │ │ ├── VPDocAsideOutline.vue │ │ │ │ ├── VPDocAsideSponsors.vue │ │ │ │ ├── VPDocFooter.vue │ │ │ │ ├── VPDocFooterLastUpdated.vue │ │ │ │ ├── VPDocOutlineItem.vue │ │ │ │ ├── VPFeature.vue │ │ │ │ ├── VPFeatures.vue │ │ │ │ ├── VPFlyout.vue │ │ │ │ ├── VPFooter.vue │ │ │ │ ├── VPHero.vue │ │ │ │ ├── VPHome.vue │ │ │ │ ├── VPHomeContent.vue │ │ │ │ ├── VPHomeFeatures.vue │ │ │ │ ├── VPHomeHero.vue │ │ │ │ ├── VPHomeSponsors.vue │ │ │ │ ├── VPImage.vue │ │ │ │ ├── VPLink.vue │ │ │ │ ├── VPLocalNav.vue │ │ │ │ ├── VPLocalNavOutlineDropdown.vue │ │ │ │ ├── VPLocalSearchBox.vue │ │ │ │ ├── VPMenu.vue │ │ │ │ ├── VPMenuGroup.vue │ │ │ │ ├── VPMenuLink.vue │ │ │ │ ├── VPNav.vue │ │ │ │ ├── VPNavBar.vue │ │ │ │ ├── VPNavBarAppearance.vue │ │ │ │ ├── VPNavBarExtra.vue │ │ │ │ ├── VPNavBarHamburger.vue │ │ │ │ ├── VPNavBarMenu.vue │ │ │ │ ├── VPNavBarMenuGroup.vue │ │ │ │ ├── VPNavBarMenuLink.vue │ │ │ │ ├── VPNavBarSearch.vue │ │ │ │ ├── VPNavBarSearchButton.vue │ │ │ │ ├── VPNavBarSocialLinks.vue │ │ │ │ ├── VPNavBarTitle.vue │ │ │ │ ├── VPNavBarTranslations.vue │ │ │ │ ├── VPNavScreen.vue │ │ │ │ ├── VPNavScreenAppearance.vue │ │ │ │ ├── VPNavScreenMenu.vue │ │ │ │ ├── VPNavScreenMenuGroup.vue │ │ │ │ ├── VPNavScreenMenuGroupLink.vue │ │ │ │ ├── VPNavScreenMenuGroupSection.vue │ │ │ │ ├── VPNavScreenMenuLink.vue │ │ │ │ ├── VPNavScreenSocialLinks.vue │ │ │ │ ├── VPNavScreenTranslations.vue │ │ │ │ ├── VPPage.vue │ │ │ │ ├── VPSidebar.vue │ │ │ │ ├── VPSidebarGroup.vue │ │ │ │ ├── VPSidebarItem.vue │ │ │ │ ├── VPSkipLink.vue │ │ │ │ ├── VPSocialLink.vue │ │ │ │ ├── VPSocialLinks.vue │ │ │ │ ├── VPSponsors.vue │ │ │ │ ├── VPSponsorsGrid.vue │ │ │ │ ├── VPSwitch.vue │ │ │ │ ├── VPSwitchAppearance.vue │ │ │ │ ├── VPTeamMembers.vue │ │ │ │ ├── VPTeamMembersItem.vue │ │ │ │ ├── VPTeamPage.vue │ │ │ │ ├── VPTeamPageSection.vue │ │ │ │ ├── VPTeamPageTitle.vue │ │ │ │ └── icons │ │ │ │ │ ├── VPIconAlignJustify.vue │ │ │ │ │ ├── VPIconAlignLeft.vue │ │ │ │ │ ├── VPIconAlignRight.vue │ │ │ │ │ ├── VPIconArrowLeft.vue │ │ │ │ │ ├── VPIconArrowRight.vue │ │ │ │ │ ├── VPIconChevronDown.vue │ │ │ │ │ ├── VPIconChevronLeft.vue │ │ │ │ │ ├── VPIconChevronRight.vue │ │ │ │ │ ├── VPIconChevronUp.vue │ │ │ │ │ ├── VPIconEdit.vue │ │ │ │ │ ├── VPIconHeart.vue │ │ │ │ │ ├── VPIconLanguages.vue │ │ │ │ │ ├── VPIconMinus.vue │ │ │ │ │ ├── VPIconMinusSquare.vue │ │ │ │ │ ├── VPIconMoon.vue │ │ │ │ │ ├── VPIconMoreHorizontal.vue │ │ │ │ │ ├── VPIconPlus.vue │ │ │ │ │ ├── VPIconPlusSquare.vue │ │ │ │ │ └── VPIconSun.vue │ │ │ ├── composables │ │ │ │ ├── aside.js │ │ │ │ ├── data.js │ │ │ │ ├── edit-link.js │ │ │ │ ├── flyout.js │ │ │ │ ├── langs.js │ │ │ │ ├── local-nav.js │ │ │ │ ├── nav.js │ │ │ │ ├── outline.js │ │ │ │ ├── prev-next.js │ │ │ │ ├── sidebar.js │ │ │ │ └── sponsor-grid.js │ │ │ ├── custom.scss │ │ │ ├── fonts │ │ │ │ ├── inter-italic-cyrillic-ext.woff2 │ │ │ │ ├── inter-italic-cyrillic.woff2 │ │ │ │ ├── inter-italic-greek-ext.woff2 │ │ │ │ ├── inter-italic-greek.woff2 │ │ │ │ ├── inter-italic-latin-ext.woff2 │ │ │ │ ├── inter-italic-latin.woff2 │ │ │ │ ├── inter-italic-vietnamese.woff2 │ │ │ │ ├── inter-roman-cyrillic-ext.woff2 │ │ │ │ ├── inter-roman-cyrillic.woff2 │ │ │ │ ├── inter-roman-greek-ext.woff2 │ │ │ │ ├── inter-roman-greek.woff2 │ │ │ │ ├── inter-roman-latin-ext.woff2 │ │ │ │ ├── inter-roman-latin.woff2 │ │ │ │ └── inter-roman-vietnamese.woff2 │ │ │ ├── index.js │ │ │ ├── styles │ │ │ │ ├── base.css │ │ │ │ ├── components │ │ │ │ │ ├── custom-block.css │ │ │ │ │ ├── vp-code-group.css │ │ │ │ │ ├── vp-code.css │ │ │ │ │ ├── vp-doc.css │ │ │ │ │ └── vp-sponsor.css │ │ │ │ ├── fonts.css │ │ │ │ ├── icons.css │ │ │ │ ├── utils.css │ │ │ │ └── vars.css │ │ │ ├── support │ │ │ │ ├── lru.js │ │ │ │ ├── sidebar.js │ │ │ │ ├── translation.js │ │ │ │ └── utils.js │ │ │ └── theme.ts │ │ │ └── without-fonts.js │ ├── Components │ │ ├── AutoComplete │ │ │ └── index.md │ │ ├── Filter │ │ │ └── index.md │ │ ├── Navigator │ │ │ └── index.md │ │ ├── Overlay │ │ │ └── index.md │ │ ├── ScrollIframe │ │ │ └── index.md │ │ ├── TiptapEditor │ │ │ └── index.md │ │ ├── VXAvatar │ │ │ └── index.md │ │ ├── VXBreadcrumbs │ │ │ └── index.md │ │ ├── VXBtn │ │ │ └── index.md │ │ ├── VXBtnGroup │ │ │ └── index.md │ │ ├── VXChart │ │ │ └── index.md │ │ ├── VXCheckbox │ │ │ └── index.md │ │ ├── VXChip │ │ │ └── index.md │ │ ├── VXDatePicker │ │ │ └── index.md │ │ ├── VXDialog │ │ │ └── index.md │ │ ├── VXField │ │ │ ├── index.md │ │ │ └── sendVariables.md │ │ ├── VXLabel │ │ │ └── index.md │ │ ├── VXModelConverter │ │ │ └── index.md │ │ ├── VXModelProxy │ │ │ └── index.md │ │ ├── VXPagination │ │ │ └── index.md │ │ ├── VXRangePicker │ │ │ └── index.md │ │ ├── VXSegmentForm │ │ │ └── index.md │ │ ├── VXSelect │ │ │ └── index.md │ │ ├── VXTabs │ │ │ └── index.md │ │ ├── VXTimePicker │ │ │ └── index.md │ │ ├── VXToolbar │ │ │ └── index.md │ │ └── VXTreeview │ │ │ └── index.md │ ├── index.md │ ├── postcss.config.mjs │ ├── public │ │ ├── iframe.html │ │ ├── imgs │ │ │ └── vx-avatar-example.png │ │ └── logo.svg │ ├── sidebar.ts │ └── vite.config.ts ├── index.html ├── package.json ├── patches │ └── @vitepress-code-preview__container.patch ├── pnpm-lock.yaml ├── public │ ├── favicon.ico │ └── iframe.html ├── scripts │ └── new-demo-doc.ts ├── src │ └── lib │ │ ├── Autocomplete.vue │ │ ├── Breadcrumbs │ │ └── VXBreadcrumbs.vue │ │ ├── Chart │ │ ├── FunnelChart.vue │ │ ├── VXChart.vue │ │ ├── presets.config.ts │ │ └── useVxChartMergeOpts.ts │ │ ├── Common │ │ ├── VXBtn.vue │ │ ├── VXBtnGroup.vue │ │ ├── VXChip.vue │ │ ├── VXDialog.vue │ │ ├── VXLabel.vue │ │ ├── VXPagination.vue │ │ └── VXToolBar.vue │ │ ├── Datepicker.vue │ │ ├── Datetimepicker.vue │ │ ├── Filter │ │ ├── Constants.ts │ │ ├── FilterData.ts │ │ ├── Model.ts │ │ ├── components │ │ │ ├── AutoCompleteItem.vue │ │ │ ├── DateItem.vue │ │ │ ├── DatePickerItem.vue │ │ │ ├── DateRangeItem.vue │ │ │ ├── DateRangePickerItem.vue │ │ │ ├── DatetimeRangeItem.vue │ │ │ ├── DatetimeRangePickerItem.vue │ │ │ ├── FilterButton.vue │ │ │ ├── FilterButtonBody.vue │ │ │ ├── ItemFilter.vue │ │ │ ├── LinkageSelectItem.vue │ │ │ ├── LinkageSelectItemRemote.vue │ │ │ ├── MultipleSelectItem.vue │ │ │ ├── NumberItem.vue │ │ │ ├── SelectItem.vue │ │ │ └── StringItem.vue │ │ └── index.vue │ │ ├── Form │ │ ├── VXCheckbox.vue │ │ ├── VXDatePicker │ │ │ ├── DatePicker.vue │ │ │ ├── DatePickerBase.vue │ │ │ ├── RangePicker.vue │ │ │ ├── TimePicker.vue │ │ │ └── TimeSelect.vue │ │ ├── VXField.vue │ │ ├── VXSegmentForm │ │ │ ├── ConditionSwitch.vue │ │ │ ├── SegmentItem.vue │ │ │ ├── SegmentItemGroup.vue │ │ │ ├── index.vue │ │ │ ├── type.d.ts │ │ │ └── useUtils.ts │ │ └── VXSelect.vue │ │ ├── Helpers.tsx │ │ ├── IframeEmitter.vue │ │ ├── LinkageSelect.vue │ │ ├── LinkageSelectRemote │ │ ├── components │ │ │ └── LinkSelectAutoComplete.vue │ │ └── index.vue │ │ ├── MessageListener.vue │ │ ├── Overlay.vue │ │ ├── RestoreScrollListener.vue │ │ ├── ScrollIframe.vue │ │ ├── SelectMany.vue │ │ ├── SendVariables.vue │ │ ├── Tabs │ │ └── VXTabs.vue │ │ ├── TextDatepicker.vue │ │ ├── TiptapEditor │ │ ├── Extensions │ │ │ ├── CallbackActionButton.ts │ │ │ ├── CallbackActionButton.vue │ │ │ └── ImageGlue.vue │ │ └── TiptapEditor.vue │ │ ├── Treeview │ │ └── VXTreeview.vue │ │ ├── VXAvatar.vue │ │ ├── VXModelProxy.vue │ │ ├── __tests__ │ │ ├── Autocomplete.spec.ts │ │ ├── Datepicker.spec.ts │ │ ├── Datetimepicker.spec.ts │ │ ├── Filter.spec.ts │ │ ├── LinkSelect.spec.ts │ │ ├── SelectMany.spec.ts │ │ ├── TextDatepicker.spec.ts │ │ ├── handler.ts │ │ └── testutils.ts │ │ ├── composables │ │ ├── forwardRefs.ts │ │ ├── useBindingValue.ts │ │ ├── useColor.ts │ │ ├── useDatePicker.ts │ │ ├── useEventListener.ts │ │ ├── useFilteredAttrs.ts │ │ └── useVDatePicker.ts │ │ ├── icons │ │ ├── checkbox-filled-outline.vue │ │ └── checkbox-on-filled-outline.vue │ │ ├── main.ts │ │ ├── plugins │ │ ├── README.md │ │ ├── i18n.ts │ │ ├── index.ts │ │ ├── theme.ts │ │ ├── tiptap.ts │ │ └── vuetify.ts │ │ ├── scss │ │ ├── _fixer.scss │ │ ├── _mixins.scss │ │ ├── _utils.scss │ │ ├── _variables.scss │ │ ├── _vuetify.scss │ │ ├── components │ │ │ ├── _ActivityTimeLine.scss │ │ │ ├── _AutoComplete.scss │ │ │ ├── _Dialog.scss │ │ │ ├── _Navigation.scss │ │ │ ├── _Section.scss │ │ │ ├── _SlideGroup.scss │ │ │ ├── _VBtn.scss │ │ │ ├── _VCard.scss │ │ │ ├── _VField.scss │ │ │ ├── _VFilter.scss │ │ │ ├── _VPagination.scss │ │ │ ├── _VTable.scss │ │ │ ├── _VTextarea.scss │ │ │ ├── _VVersionSelect.scss │ │ │ ├── _imgUploader.scss │ │ │ ├── _vChip.scss │ │ │ └── _vTabs.scss │ │ ├── index.scss │ │ ├── page │ │ │ ├── _Detailing.scss │ │ │ ├── _Listing.scss │ │ │ └── _PageBuilder.scss │ │ └── sites │ │ │ └── k-theme.scss │ │ └── vite-env.d.ts ├── tsconfig-build.json ├── tsconfig.json ├── tsconfig.node.json ├── update-tip-tap.sh ├── vite.config.ts └── vitest.config.ts ├── vx-avatar.go ├── vx-breadcrumbs.go ├── vx-btn-group.go ├── vx-btn.go ├── vx-chart.go ├── vx-checkbox.go ├── vx-chip.go ├── vx-date-picker.go ├── vx-dialog.go ├── vx-field.go ├── vx-iframe-emitter.go ├── vx-label.go ├── vx-model-proxy.go ├── vx-pagination.go ├── vx-range-picker.go ├── vx-segment-form.go ├── vx-select.go ├── vx-send-variables.go ├── vx-tabs.go ├── vx-time-picker.go ├── vx-toolbar.go └── vx-treeview.go /.github/workflows/doc-build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build-and-deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: checkout repository 13 | uses: actions/checkout@v3 14 | 15 | - name: set Node.js environment 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: '20.x' 19 | 20 | - name: Install pnpm 21 | run: npm install -g pnpm@9.15.5 22 | 23 | - name: Install dep 24 | working-directory: ui/vuetifyx/vuetifyxjs 25 | run: pnpm install 26 | 27 | - name: build doc 28 | working-directory: ui/vuetifyx/vuetifyxjs 29 | run: pnpm run docs:build 30 | 31 | - name: push to gh-pages branch 32 | uses: peaceiris/actions-gh-pages@v3 33 | with: 34 | github_token: ${{ secrets.GITHUB_TOKEN }} 35 | publish_dir: ui/vuetifyx/vuetifyxjs/docs/.vitepress/dist 36 | publish_branch: gh-pages -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: go 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths-ignore: 7 | - '**/dist/**' 8 | - '**/*.md' 9 | - '**/docs/**' 10 | pull_request: 11 | branches: [master] 12 | paths-ignore: 13 | - '**/dist/**' 14 | - '**/*.md' 15 | - '**/docs/**' 16 | 17 | jobs: 18 | test: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: szenius/set-timezone@v1.0 22 | with: 23 | timezoneLinux: 'Asia/Shanghai' 24 | 25 | - uses: actions/checkout@v2 26 | 27 | - name: Set up Go 28 | uses: actions/setup-go@v2 29 | with: 30 | go-version: 1.22.3 31 | 32 | - name: Build 33 | run: go build -v ./... 34 | 35 | - name: Test 36 | run: go test -v ./... 37 | -------------------------------------------------------------------------------- /.github/workflows/vuetifyjs-build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Commit Artifacts 2 | 3 | on: 4 | pull_request: 5 | branches: [master, release-test] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 0 # 确保获取完整的提交历史 16 | 17 | - name: Set up Node.js 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: '18' 21 | 22 | - name: Install pnpm 23 | run: npm install -g pnpm@9.15.5 24 | 25 | - name: Build project 26 | run: | 27 | cd ui/vuetifyx/vuetifyxjs 28 | pnpm install 29 | pnpm run build 30 | 31 | - name: Commit build artifacts 32 | run: | 33 | git config --global user.name 'github-actions[bot]' 34 | git config --global user.email 'github-actions[bot]@users.noreply.github.com' 35 | 36 | # 强制添加被 .gitignore 忽略的 dist 目录 37 | git add ui/vuetifyx/vuetifyxjs/dist -f 38 | 39 | # 检查是否有更改 40 | if ! git diff --cached --quiet; then 41 | git commit -m 'Add build artifacts' 42 | git push origin HEAD:${{ github.head_ref }} 43 | else 44 | echo "No changes detected; skipping commit." 45 | fi 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | -------------------------------------------------------------------------------- /.github/workflows/vuetifyjs-test.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: vuetifyxjs 5 | 6 | on: 7 | push: 8 | branches: [main] 9 | paths-ignore: 10 | - '**/dist/**' 11 | - '**/*.md' 12 | - '**/docs/**' 13 | pull_request: 14 | branches: [main] 15 | paths-ignore: 16 | - '**/dist/**' 17 | - '**/*.md' 18 | - '**/docs/**' 19 | 20 | jobs: 21 | test: 22 | runs-on: ubuntu-latest 23 | strategy: 24 | matrix: 25 | node-version: [18.x] 26 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 27 | 28 | steps: 29 | - uses: szenius/set-timezone@v1.0 30 | with: 31 | timezoneLinux: 'Asia/Shanghai' 32 | 33 | - uses: actions/checkout@v2 34 | - name: Use Node.js ${{ matrix.node-version }} 35 | uses: actions/setup-node@v2 36 | with: 37 | node-version: ${{ matrix.node-version }} 38 | 39 | - name: Install pnpm 40 | run: npm install -g pnpm@9.15.5 41 | - name: Build and Test 42 | run: cd ./ui/vuetifyx/vuetifyxjs/ && pnpm install && pnpm run build && pnpm run test:unit 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.DS_Store 3 | __* 4 | !__tests__ 5 | vite.config.ts.timestamp-*.mjs 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright © 2019-2023 ThePlant 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /exchange/container.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | type Reader interface { 4 | Header() []string 5 | ReadRow() ([]string, error) 6 | Next() bool 7 | Total() uint 8 | } 9 | 10 | type Writer interface { 11 | WriteHeader([]string) error 12 | WriteRow([]string) error 13 | Flush() error 14 | } 15 | -------------------------------------------------------------------------------- /exchange/meta.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/iancoleman/strcase" 7 | ) 8 | 9 | type MetaValues interface { 10 | Get(field string) (val string) 11 | } 12 | 13 | type Meta struct { 14 | field string 15 | snakeField string 16 | columnHeader string 17 | primaryKey bool 18 | 19 | setter MetaSetter 20 | valuer MetaValuer 21 | } 22 | 23 | func NewMeta(field string) *Meta { 24 | field = strings.TrimSpace(field) 25 | return &Meta{ 26 | field: field, 27 | columnHeader: field, 28 | snakeField: strcase.ToSnake(field), 29 | } 30 | } 31 | 32 | // default is field name 33 | func (m *Meta) Header(s string) *Meta { 34 | m.columnHeader = strings.TrimSpace(s) 35 | return m 36 | } 37 | 38 | func (m *Meta) PrimaryKey(b bool) *Meta { 39 | m.primaryKey = b 40 | return m 41 | } 42 | 43 | type MetaSetter func(record interface{}, value string, metaValues MetaValues) error 44 | 45 | // set values to special fields 46 | // e.g. time.Time, struct, associated records ... 47 | func (m *Meta) Setter(f MetaSetter) *Meta { 48 | m.setter = f 49 | return m 50 | } 51 | 52 | type MetaValuer func(record interface{}) (string, error) 53 | 54 | // format values when exporting 55 | func (m *Meta) Valuer(f MetaValuer) *Meta { 56 | m.valuer = f 57 | return m 58 | } 59 | -------------------------------------------------------------------------------- /exchange/options.go: -------------------------------------------------------------------------------- 1 | package exchange 2 | 3 | type ImporterExecOption interface { 4 | iePrivate() 5 | } 6 | 7 | type ExporterExecOption interface { 8 | eePrivate() 9 | } 10 | 11 | type ExecOption interface { 12 | ImporterExecOption 13 | ExporterExecOption 14 | } 15 | 16 | func MaxParamsPerSQL(v int) ExecOption { 17 | return &maxParamsPerSQLOption{v} 18 | } 19 | 20 | type maxParamsPerSQLOption struct { 21 | v int 22 | } 23 | 24 | var ( 25 | _ ImporterExecOption = (*maxParamsPerSQLOption)(nil) 26 | _ ExporterExecOption = (*maxParamsPerSQLOption)(nil) 27 | ) 28 | 29 | func (o *maxParamsPerSQLOption) iePrivate() {} 30 | func (o *maxParamsPerSQLOption) eePrivate() {} 31 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/README.md: -------------------------------------------------------------------------------- 1 | # i18n-transfer 2 | 3 | ## Usage 4 | 5 | - Install the i18n-transfer. 6 | 7 | ``` 8 | $ go install github.com/qor5/x/v3/i18n/i18n-transfer@latest 9 | ``` 10 | 11 | - Must cd root dir of the project. 12 | 13 | ``` 14 | $ cd $GOPATH/src/github.com/[your project] 15 | ``` 16 | 17 | example: 18 | ``` 19 | $ cd $GOPATH/src/github.com/qor5/x 20 | ``` 21 | 22 | 23 | - Run i18n-transfer. 24 | 25 | ``` 26 | 27 | $ i18n-transfer 28 | Use the arrow keys to navigate: ↓ ↑ → ← 29 | ? Import Or Export: 30 | ▸ Import 31 | Export 32 | 33 | ``` 34 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/csv/csv_to_translations_map.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "encoding/csv" 5 | "os" 6 | ) 7 | 8 | func CsvToTranslationsMap(csvPath string) (translationsMap map[string]map[string]string, err error) { 9 | f, err := os.Open(csvPath) 10 | if err != nil { 11 | return 12 | } 13 | 14 | r := csv.NewReader(f) 15 | 16 | records, err := r.ReadAll() 17 | if err != nil { 18 | return 19 | } 20 | 21 | keyValueMap := make(map[int]map[int]string) 22 | for i, record := range records { 23 | for j, value := range record { 24 | if keyValueMap[i] == nil { 25 | keyValueMap[i] = make(map[int]string) 26 | } 27 | keyValueMap[i][j] = value 28 | } 29 | } 30 | 31 | translationsMap = make(map[string]map[string]string) 32 | for i, record := range records { 33 | for j, value := range record { 34 | if translationsMap[records[0][j]] == nil { 35 | translationsMap[records[0][j]] = make(map[string]string) 36 | } 37 | translationsMap[records[0][j]][records[i][0]] = value 38 | } 39 | } 40 | return 41 | } 42 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/parser/utils.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | go_path "path" 5 | "strings" 6 | ) 7 | 8 | func getTranslationMapKey(path, keyName, projectPath string) string { 9 | temp := strings.Split(projectPath, "/") 10 | return strings.TrimPrefix(go_path.Join(path, keyName), strings.TrimSuffix(strings.Join(temp[:len(temp)-1], "/"), "/")+"/") 11 | } 12 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/test/mock/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/qor5/x/v3/i18n" 5 | "github.com/qor5/x/v3/i18n/i18n-transfer/test/mock/messages" 6 | "golang.org/x/text/language" 7 | ) 8 | 9 | func main() { 10 | b := i18n.New() 11 | b.SupportLanguages(language.Chinese, language.Japanese). 12 | RegisterForModule(language.Chinese, messages.I18nModuleKey, messages.User_CN). 13 | RegisterForModule(language.Japanese, messages.I18nModuleKey, messages.User_JP) 14 | } 15 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/test/mock/messages/message.go: -------------------------------------------------------------------------------- 1 | package messages 2 | 3 | import "github.com/qor5/x/v3/i18n/i18n-transfer/test/mock/out_messages" 4 | 5 | const I18nModuleKey = "i18nModuleKey" 6 | 7 | type UserMessage struct { 8 | name string 9 | Email 10 | out_messages.Detail 11 | } 12 | 13 | type Email struct { 14 | Email string 15 | Phone 16 | } 17 | 18 | var User_CN = &UserMessage{ 19 | name: "User CN", 20 | Email: Email_CN, 21 | Detail: out_messages.Detail_CN, 22 | } 23 | 24 | var Email_CN = Email{ 25 | Email: "terry@theplant.cn", 26 | Phone: Phone_CN, 27 | } 28 | 29 | var User_JP = &UserMessage{ 30 | name: "User JP", 31 | Email: Email_JP, 32 | Detail: out_messages.Detail_JP, 33 | } 34 | 35 | var Email_JP = Email{ 36 | Email: "terry@theplant.jp", 37 | Phone: Phone_JP, 38 | } 39 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/test/mock/messages/phone.go: -------------------------------------------------------------------------------- 1 | package messages 2 | 3 | type Phone struct { 4 | PhoneNumber string 5 | } 6 | 7 | var Phone_CN = Phone{ 8 | PhoneNumber: "+86", 9 | } 10 | 11 | var Phone_JP = Phone{ 12 | PhoneNumber: "+100", 13 | } 14 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/test/mock/out_messages/message.go: -------------------------------------------------------------------------------- 1 | package out_messages 2 | 3 | type Detail struct { 4 | Age string 5 | } 6 | 7 | var Detail_CN = Detail{ 8 | Age: "13", 9 | } 10 | 11 | var Detail_JP = Detail{ 12 | Age: "27", 13 | } 14 | -------------------------------------------------------------------------------- /i18n/i18n-transfer/test/mock/test_import.csv: -------------------------------------------------------------------------------- 1 | Translation Keys,Chinese,Japanese 2 | mock/messages/Email,New CNEmail,New JPEmail 3 | mock/messages/PhoneNumber,+8666,+100000 4 | mock/messages/name,New User CN,New User JP -------------------------------------------------------------------------------- /login/assets.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "embed" 5 | ) 6 | 7 | //go:embed assets 8 | var assetsFS embed.FS 9 | 10 | var assetsPathPrefix = "/auth/assets/" 11 | var ( 12 | StyleCSSURL = assetsPathPrefix + "style.css" 13 | ZxcvbnJSURL = assetsPathPrefix + "zxcvbn.js" 14 | ) 15 | -------------------------------------------------------------------------------- /login/buildcss.sh: -------------------------------------------------------------------------------- 1 | npx -y tailwindcss@v3 --minify -o assets/style.css 2 | -------------------------------------------------------------------------------- /login/helpers_test.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/google/go-cmp/cmp" 7 | ) 8 | 9 | func TestMustSetQuery(t *testing.T) { 10 | for _, c := range []struct { 11 | name string 12 | u string 13 | kvs []string 14 | expect string 15 | }{ 16 | { 17 | name: "no query", 18 | u: "/a/b", 19 | kvs: []string{ 20 | "k1", "v1", 21 | "k2", "v2", 22 | }, 23 | expect: "/a/b?k1=v1&k2=v2", 24 | }, 25 | { 26 | name: "has query", 27 | u: "/a/b?a=1", 28 | kvs: []string{ 29 | "k1", "v1", 30 | "k2", "v2", 31 | }, 32 | expect: "/a/b?a=1&k1=v1&k2=v2", 33 | }, 34 | { 35 | name: "has same query", 36 | u: "/a/b?a=1&k2=v22", 37 | kvs: []string{ 38 | "k1", "v1", 39 | "k2", "v2", 40 | }, 41 | expect: "/a/b?a=1&k1=v1&k2=v2", 42 | }, 43 | { 44 | name: "full url", 45 | u: "https://example.com/a/b?a=1&k2=v22", 46 | kvs: []string{ 47 | "k1", "v1", 48 | "k2", "v2", 49 | }, 50 | expect: "https://example.com/a/b?a=1&k1=v1&k2=v2", 51 | }, 52 | } { 53 | if diff := cmp.Diff(c.expect, MustSetQuery(c.u, c.kvs...)); diff != "" { 54 | t.Fatalf("%s: %s\n", c.name, diff) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /login/primary_field.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/iancoleman/strcase" 7 | "github.com/sunfmin/reflectutils" 8 | ) 9 | 10 | type PrimaryFielder interface { 11 | PrimaryField() string 12 | } 13 | 14 | func primaryField(obj interface{}) string { 15 | f := "ID" 16 | if v, ok := obj.(PrimaryFielder); ok { 17 | f = v.PrimaryField() 18 | } 19 | return f 20 | } 21 | 22 | func snakePrimaryField(obj interface{}) string { 23 | return strcase.ToSnake(primaryField(obj)) 24 | } 25 | 26 | func objectID(obj interface{}) string { 27 | return fmt.Sprint(reflectutils.MustGet(obj, primaryField(obj))) 28 | } 29 | -------------------------------------------------------------------------------- /login/session_secure.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "crypto/rand" 5 | "encoding/hex" 6 | "fmt" 7 | 8 | "gorm.io/gorm" 9 | ) 10 | 11 | type SessionSecurer interface { 12 | UpdateSecure(db *gorm.DB, model interface{}, id string) error 13 | GetSecure() string 14 | } 15 | 16 | type SessionSecure struct { 17 | SessionSecure string `gorm:"size:32"` 18 | } 19 | 20 | var _ SessionSecurer = (*SessionSecure)(nil) 21 | 22 | func (ss *SessionSecure) UpdateSecure(db *gorm.DB, model interface{}, id string) error { 23 | b := make([]byte, 16) 24 | rand.Read(b) 25 | secure := hex.EncodeToString(b) 26 | err := db.Model(model). 27 | Where(fmt.Sprintf("%s = ?", snakePrimaryField(model)), id). 28 | Updates(map[string]interface{}{ 29 | "session_secure": secure, 30 | }). 31 | Error 32 | if err != nil { 33 | return err 34 | } 35 | ss.SessionSecure = secure 36 | return nil 37 | } 38 | 39 | func (ss *SessionSecure) GetSecure() string { 40 | return ss.SessionSecure 41 | } 42 | -------------------------------------------------------------------------------- /login/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ['./**/*.go'], 3 | } 4 | -------------------------------------------------------------------------------- /login/utils.go: -------------------------------------------------------------------------------- 1 | package login 2 | 3 | import ( 4 | "net/http" 5 | 6 | "gorm.io/gorm" 7 | ) 8 | 9 | func RevokeTOTP( 10 | ssup SessionSecureUserPasser, 11 | db *gorm.DB, 12 | userModel interface{}, 13 | userID string, 14 | ) (err error) { 15 | if err = ssup.SetIsTOTPSetup(db, userModel, false); err != nil { 16 | return err 17 | } 18 | if err = ssup.UpdateSecure(db, userModel, userID); err != nil { 19 | return err 20 | } 21 | return nil 22 | } 23 | 24 | func GetSessionToken(b *Builder, r *http.Request) string { 25 | c, err := r.Cookie(b.authCookieName) 26 | if err != nil { 27 | return "" 28 | } 29 | return c.Value 30 | } 31 | -------------------------------------------------------------------------------- /oss/.gitignore: -------------------------------------------------------------------------------- 1 | test_env 2 | -------------------------------------------------------------------------------- /oss/aliyun/README.md: -------------------------------------------------------------------------------- 1 | # Aliyun 2 | 3 | [Aliyun](http://aliyun.com) backend for [QOR OSS](https://github.com/qor/oss) 4 | 5 | ## Usage 6 | 7 | ```go 8 | import "github.com/qor/oss/aliyun" 9 | 10 | func main() { 11 | storage := aliyun.New(&aliyun.Config{ 12 | AccessID: "access_id", 13 | AccessKey: "access_id", 14 | Bucket: "bucket", 15 | Endpoint: "oss-cn-hangzhou.aliyuncs.com", 16 | }) 17 | 18 | // Save a reader interface into storage 19 | storage.Put("/sample.txt", reader) 20 | 21 | // Get file with path 22 | storage.Get("/sample.txt") 23 | 24 | // Get object as io.ReadCloser 25 | storage.GetStream("/sample.txt") 26 | 27 | // Delete file with path 28 | storage.Delete("/sample.txt") 29 | 30 | // List all objects under path 31 | storage.List("/") 32 | 33 | // Get Public Accessible URL (useful if current file saved privately) 34 | storage.GetURL("/sample.txt") 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /oss/filesystem/filesystem_test.go: -------------------------------------------------------------------------------- 1 | package filesystem 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/qor5/x/v3/oss/tests" 7 | ) 8 | 9 | func TestAll(t *testing.T) { 10 | fileSystem := New("/tmp") 11 | tests.TestAll(fileSystem, t) 12 | } 13 | -------------------------------------------------------------------------------- /oss/oss.go: -------------------------------------------------------------------------------- 1 | package oss 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "os" 7 | "time" 8 | ) 9 | 10 | // StorageInterface define common API to operate storage 11 | type StorageInterface interface { 12 | Get(ctx context.Context, path string) (*os.File, error) 13 | GetStream(ctx context.Context, path string) (io.ReadCloser, error) 14 | Put(ctx context.Context, path string, reader io.Reader) (*Object, error) 15 | Delete(ctx context.Context, path string) error 16 | List(ctx context.Context, path string) ([]*Object, error) 17 | GetURL(ctx context.Context, path string) (string, error) 18 | GetEndpoint(ctx context.Context) string 19 | } 20 | 21 | // Object content object 22 | type Object struct { 23 | Path string 24 | Name string 25 | LastModified *time.Time 26 | StorageInterface StorageInterface 27 | } 28 | 29 | // Get retrieve object's content 30 | func (object Object) Get(ctx context.Context) (*os.File, error) { 31 | return object.StorageInterface.Get(ctx, object.Path) 32 | } 33 | -------------------------------------------------------------------------------- /oss/qiniu/README.md: -------------------------------------------------------------------------------- 1 | # Qiniu 2 | 3 | [Qiniu](https://www.qiniu.com) backend for [QOR OSS](https://github.com/qor/oss) 4 | 5 | ## Usage 6 | 7 | ```go 8 | import "github.com/qor/oss/qiniu" 9 | 10 | func main() { 11 | storage := qiniu.New(&qiniu.Config{ 12 | AccessID: "access_id", 13 | AccessKey: "access_key", 14 | Bucket: "bucket", 15 | Region: "huadong", 16 | Endpoint: "https://up.qiniup.com", 17 | }) 18 | 19 | // Save a reader interface into storage 20 | storage.Put("/sample.txt", reader) 21 | 22 | // Get file with path 23 | storage.Get("/sample.txt") 24 | 25 | // Get object as io.ReadCloser 26 | storage.GetStream("/sample.txt") 27 | 28 | // Delete file with path 29 | storage.Delete("/sample.txt") 30 | 31 | // List all objects under path 32 | storage.List("/") 33 | 34 | // Get Public Accessible URL (useful if current file saved privately) 35 | storage.GetURL("/sample.txt") 36 | } 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /oss/s3/README.md: -------------------------------------------------------------------------------- 1 | # AWS S3 2 | 3 | [AWS S3](https://aws.amazon.com/cn/s3/) backend for [QOR OSS](https://github.com/qor/oss) 4 | 5 | ## Usage 6 | 7 | ```go 8 | import "github.com/qor/oss/aliyun" 9 | 10 | func main() { 11 | storage := s3.New(s3.Config{ 12 | AccessID: "access_id", 13 | AccessKey: "access_key", 14 | Region: "region", 15 | Bucket: "bucket", 16 | Endpoint: "cdn.getqor.com", 17 | ACL: awss3.BucketCannedACLPublicRead, 18 | }) 19 | 20 | // Save a reader interface into storage 21 | storage.Put("/sample.txt", reader) 22 | 23 | // Get file with path 24 | storage.Get("/sample.txt") 25 | 26 | // Get object as io.ReadCloser 27 | storage.GetStream("/sample.txt") 28 | 29 | // Delete file with path 30 | storage.Delete("/sample.txt") 31 | 32 | // List all objects under path 33 | storage.List("/") 34 | 35 | // Get Public Accessible URL (useful if current file saved privately) 36 | storage.GetURL("/sample.txt") 37 | } 38 | ``` 39 | 40 | 41 | -------------------------------------------------------------------------------- /oss/tencent/tencent_test.go: -------------------------------------------------------------------------------- 1 | package tencent 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | "os" 8 | "testing" 9 | 10 | "github.com/jinzhu/configor" 11 | "github.com/qor5/x/v3/oss/tests" 12 | ) 13 | 14 | var client *Client 15 | 16 | func init() { 17 | cfg := Config{} 18 | configor.New(&configor.Config{ENVPrefix: "TENCENT"}).Load(&cfg) 19 | 20 | if len(cfg.AppID) == 0 { 21 | fmt.Println("No tencent configuration") 22 | return 23 | } 24 | 25 | client = New(&cfg) 26 | } 27 | 28 | func TestClient_Get(t *testing.T) { 29 | 30 | } 31 | 32 | func TestClient_Put(t *testing.T) { 33 | if client == nil { 34 | t.Skip(`skip because of no config: `) 35 | } 36 | 37 | f, err := os.ReadFile("/home/owen/Downloads/2.png") 38 | if err != nil { 39 | t.Error(err) 40 | return 41 | } 42 | 43 | client.Put(context.Background(), "test.png", bytes.NewReader(f)) 44 | } 45 | 46 | func TestClient_Put2(t *testing.T) { 47 | if client == nil { 48 | t.Skip(`skip because of no config: `) 49 | } 50 | 51 | tests.TestAll(client, t) 52 | } 53 | 54 | func TestClient_Delete(t *testing.T) { 55 | if client == nil { 56 | t.Skip(`skip because of no config: `) 57 | } 58 | 59 | fmt.Println(client.Delete(context.Background(), "test.png")) 60 | } 61 | -------------------------------------------------------------------------------- /oss/tests/sample.txt: -------------------------------------------------------------------------------- 1 | sample 2 | -------------------------------------------------------------------------------- /perm/matcher.go: -------------------------------------------------------------------------------- 1 | package perm 2 | 3 | import ( 4 | "path/filepath" 5 | 6 | "github.com/ory/ladon" 7 | ) 8 | 9 | type PathMatcher struct{} 10 | 11 | func (m *PathMatcher) Matches(p ladon.Policy, haystack []string, needle string) (bool, error) { 12 | for _, h := range haystack { 13 | m, err := filepath.Match(h, needle) 14 | if err != nil { 15 | return false, err 16 | } 17 | if m { 18 | return true, nil 19 | } 20 | } 21 | return false, nil 22 | } 23 | -------------------------------------------------------------------------------- /sitemap/ping.go: -------------------------------------------------------------------------------- 1 | package sitemap 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net/http" 7 | ) 8 | 9 | type ToUrlInterface interface { 10 | ToUrl(context.Context) string 11 | } 12 | 13 | func PingBing(site ToUrlInterface, ctx context.Context) (err error) { 14 | _, err = http.Get(fmt.Sprintf("http://www.bing.com/webmaster/ping.aspx?siteMap=%s", site.ToUrl(ctx))) 15 | return 16 | } 17 | 18 | func PingGoogle(site ToUrlInterface, ctx context.Context) (err error) { 19 | _, err = http.Get(fmt.Sprintf("https://www.google.com/webmasters/sitemaps/ping?sitemap=%s", site.ToUrl(ctx))) 20 | return 21 | } 22 | 23 | func PingAll(site ToUrlInterface, ctx context.Context) (err error) { 24 | if err = PingGoogle(site, ctx); err != nil { 25 | return 26 | } 27 | 28 | if err = PingBing(site, ctx); err != nil { 29 | return 30 | } 31 | 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /ui/build_package_json.sh: -------------------------------------------------------------------------------- 1 | ROOT=$(pwd) 2 | 3 | PKGS=" 4 | $ROOT/../../web/corejs 5 | $ROOT/tiptap/tiptapjs 6 | $ROOT/vuetifyx/vuetifyxjs 7 | $ROOT/cropper/cropperjs 8 | $ROOT/redactor/redactorjs 9 | " 10 | for i in $PKGS 11 | do 12 | echo "$i" && \ 13 | cd $i && pnpm install && pnpm build 14 | done 15 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist-ssr 13 | coverage 14 | *.local 15 | 16 | /cypress/videos/ 17 | /cypress/screenshots/ 18 | 19 | # Editor directories and files 20 | .vscode/* 21 | !.vscode/extensions.json 22 | .idea 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | 29 | *.tsbuildinfo 30 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/README.md: -------------------------------------------------------------------------------- 1 | # cropperjs 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). 8 | 9 | ## Type Support for `.vue` Imports in TS 10 | 11 | TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. 12 | 13 | ## Customize configuration 14 | 15 | See [Vite Configuration Reference](https://vitejs.dev/config/). 16 | 17 | ## Project Setup 18 | 19 | ```sh 20 | pnpm install 21 | ``` 22 | 23 | ### Compile and Hot-Reload for Development 24 | 25 | ```sh 26 | pnpm dev 27 | ``` 28 | 29 | ### Type-Check, Compile and Minify for Production 30 | 31 | ```sh 32 | pnpm build 33 | ``` 34 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cropperjs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vue-tsc --noEmit && vite build ", 9 | "watch-build": "nodemon --watch src --exec 'npm run build'", 10 | "preview": "vite preview", 11 | "format": "prettier --write src/" 12 | }, 13 | "dependencies": { 14 | "cropperjs": "^1.6.2", 15 | "vue": "^3.5.13" 16 | }, 17 | "devDependencies": { 18 | "@tsconfig/node20": "^20.1.4", 19 | "@types/node": "^20.17.24", 20 | "@vitejs/plugin-vue": "^5.2.3", 21 | "@vue/tsconfig": "^0.5.1", 22 | "nodemon": "^3.1.9", 23 | "npm-run-all2": "^6.2.6", 24 | "prettier": "^3.5.3", 25 | "typescript": "~5.4.5", 26 | "vite": "^5.4.19", 27 | "vite-plugin-vue-devtools": "^7.7.2", 28 | "vue-tsc": "^2.2.8" 29 | }, 30 | "pnpm": { 31 | "overrides": { 32 | "esbuild": "0.25.0" 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ui/cropper/cropperjs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/cropper/cropperjs/public/favicon.ico -------------------------------------------------------------------------------- /ui/cropper/cropperjs/src/demo/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/src/demo/components/CropperExample.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/src/demo/main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * main.ts 3 | * 4 | * Bootstraps Vuetify and other plugins then mounts the App` 5 | */ 6 | 7 | // Plugins 8 | 9 | // Components 10 | import App from "@/demo/App.vue"; 11 | 12 | // Composables 13 | import { createApp } from "vue"; 14 | 15 | const app = createApp(App); 16 | 17 | app.mount("#app"); 18 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/src/demo/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "*.vue" { 4 | import type { DefineComponent } from "vue"; 5 | const component: DefineComponent<{}, {}, any>; 6 | export default component; 7 | } 8 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/src/lib/main.ts: -------------------------------------------------------------------------------- 1 | import { type App } from "vue"; 2 | import Cropper from "@/lib/Cropper.vue"; 3 | 4 | declare const window: any; 5 | window.__goplaidVueComponentRegisters = 6 | window.__goplaidVueComponentRegisters || []; 7 | window.__goplaidVueComponentRegisters.push((app: App, vueOptions: any): any => { 8 | app.component("vue-cropper", Cropper); 9 | }); 10 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/src/lib/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "*.vue" { 4 | import type { DefineComponent } from "vue"; 5 | const component: DefineComponent<{}, {}, any>; 6 | export default component; 7 | } 8 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 | 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*" 9 | ], 10 | "compilerOptions": { 11 | "composite": true, 12 | "noEmit": true, 13 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 14 | 15 | "module": "ESNext", 16 | "moduleResolution": "Bundler", 17 | "types": ["node"] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ui/cropper/cropperjs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import {fileURLToPath, URL} from 'node:url' 2 | 3 | import {defineConfig} from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import VueDevTools from 'vite-plugin-vue-devtools' 6 | import {resolve} from "path"; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | build: { 11 | // minify: false, 12 | lib: { 13 | entry: resolve(__dirname, 'src/lib/main.ts'), 14 | formats: ['umd'], 15 | name: 'cropper' 16 | }, 17 | copyPublicDir: false, 18 | rollupOptions: { 19 | external: ['vue'], 20 | output: { 21 | assetFileNames: (assetInfo) => { 22 | return 'cropperjs.css' 23 | }, 24 | globals: { 25 | vue: 'Vue', 26 | } 27 | } 28 | } 29 | }, 30 | plugins: [ 31 | vue(), 32 | VueDevTools(), 33 | ], 34 | resolve: { 35 | alias: { 36 | '@': fileURLToPath(new URL('./src', import.meta.url)) 37 | } 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /ui/cropper/embed.go: -------------------------------------------------------------------------------- 1 | package cropper 2 | 3 | import ( 4 | "embed" 5 | 6 | "github.com/qor5/web/v3" 7 | ) 8 | 9 | //go:embed cropperjs/dist 10 | var box embed.FS 11 | 12 | func JSComponentsPack() web.ComponentsPack { 13 | v, err := box.ReadFile("cropperjs/dist/cropperjs.umd.cjs") 14 | if err != nil { 15 | panic(err) 16 | } 17 | 18 | return web.ComponentsPack(v) 19 | } 20 | 21 | func CSSComponentsPack() web.ComponentsPack { 22 | v, err := box.ReadFile("cropperjs/dist/cropperjs.css") 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | return web.ComponentsPack(v) 28 | } 29 | -------------------------------------------------------------------------------- /ui/fileicons/embed.go: -------------------------------------------------------------------------------- 1 | package fileicons 2 | 3 | import ( 4 | "embed" 5 | "encoding/base64" 6 | "fmt" 7 | "strings" 8 | 9 | h "github.com/theplant/htmlgo" 10 | ) 11 | 12 | //go:embed icons 13 | var icons embed.FS 14 | 15 | var svgs = map[string]string{} 16 | 17 | func init() { 18 | files, err := icons.ReadDir("icons") 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | for _, f := range files { 24 | if f.IsDir() { 25 | continue 26 | } 27 | // fmt.Println(f.Name()) 28 | svg, err := icons.ReadFile(fmt.Sprintf("icons/%s", f.Name())) 29 | if err != nil { 30 | panic(err) 31 | } 32 | filetype := strings.Split(f.Name(), ".")[0] 33 | svgs[filetype] = base64.StdEncoding.EncodeToString(svg) 34 | } 35 | 36 | // fmt.Println(svgs) 37 | } 38 | 39 | func Icon(ext string) *h.HTMLTagBuilder { 40 | img, ok := svgs[ext] 41 | if !ok { 42 | img = svgs["file"] 43 | } 44 | 45 | return h.Img(fmt.Sprintf("data:image/svg+xml;base64,%s", img)) 46 | } 47 | -------------------------------------------------------------------------------- /ui/fileicons/icons/file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ui/redactor/embed.go: -------------------------------------------------------------------------------- 1 | package redactor 2 | 3 | import ( 4 | "bytes" 5 | "embed" 6 | 7 | "github.com/qor5/web/v3" 8 | ) 9 | 10 | //go:embed redactorjs 11 | var box embed.FS 12 | 13 | func JSComponentsPack() web.ComponentsPack { 14 | var js [][]byte 15 | j1, err := box.ReadFile("redactorjs/dist/redactorjs.umd.cjs") 16 | if err != nil { 17 | panic(err) 18 | } 19 | js = append(js, j1) 20 | return web.ComponentsPack(bytes.Join(js, []byte("\n\n"))) 21 | } 22 | 23 | func CSSComponentsPack() web.ComponentsPack { 24 | c, err := box.ReadFile("redactorjs/dist/redactor.css") 25 | if err != nil { 26 | panic(err) 27 | } 28 | return web.ComponentsPack(c) 29 | } 30 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist-ssr 13 | coverage 14 | *.local 15 | 16 | .vscode 17 | 18 | /cypress/videos/ 19 | /cypress/screenshots/ 20 | 21 | # Editor directories and files 22 | .vscode/* 23 | !.vscode/extensions.json 24 | .idea 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | 31 | *.tsbuildinfo 32 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/README.md: -------------------------------------------------------------------------------- 1 | # redactorjs 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). 8 | 9 | ## Customize configuration 10 | 11 | See [Vite Configuration Reference](https://vitejs.dev/config/). 12 | 13 | ## Project Setup 14 | 15 | ```sh 16 | pnpm install 17 | ``` 18 | 19 | ### Compile and Hot-Reload for Development 20 | 21 | ```sh 22 | pnpm dev 23 | ``` 24 | 25 | ### Compile and Minify for Production 26 | 27 | ```sh 28 | pnpm build 29 | ``` 30 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./src/*"] 5 | } 6 | }, 7 | "exclude": ["node_modules", "dist"] 8 | } 9 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redactorjs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "watch-build": "nodemon --watch src --exec 'npm run build'", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "vue": "^3.5.13" 14 | }, 15 | "devDependencies": { 16 | "@vitejs/plugin-vue": "^5.2.3", 17 | "nodemon": "^3.1.9", 18 | "vite": "^5.4.19", 19 | "vite-plugin-vue-devtools": "^7.7.2" 20 | }, 21 | "pnpm": { 22 | "overrides": { 23 | "esbuild": "0.25.0" 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /ui/redactor/redactorjs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/redactor/redactorjs/public/favicon.ico -------------------------------------------------------------------------------- /ui/redactor/redactorjs/src/demo/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/src/demo/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/src/lib/main.js: -------------------------------------------------------------------------------- 1 | import RichTextRedactor from "@/lib/RichTextRedactor.vue"; 2 | 3 | window.__goplaidVueComponentRegisters = window.__goplaidVueComponentRegisters || [] 4 | window.__goplaidVueComponentRegisters.push((app, vueOptions) => { 5 | app.component("redactor", RichTextRedactor) 6 | }) 7 | -------------------------------------------------------------------------------- /ui/redactor/redactorjs/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import VueDevTools from 'vite-plugin-vue-devtools' 6 | import { resolve } from 'path' 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | build: { 11 | // minify: false, 12 | lib: { 13 | entry: resolve(__dirname, 'src/lib/main.js'), 14 | formats: ['umd'], 15 | name: 'redactor' 16 | }, 17 | copyPublicDir: false, 18 | rollupOptions: { 19 | external: ['vue'], 20 | output: { 21 | assetFileNames: (assetInfo) => { 22 | return 'redactor.css' 23 | }, 24 | globals: { 25 | vue: 'Vue', 26 | } 27 | } 28 | } 29 | }, 30 | plugins: [ 31 | vue(), 32 | VueDevTools(), 33 | ], 34 | resolve: { 35 | alias: { 36 | '@': fileURLToPath(new URL('./src', import.meta.url)) 37 | } 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /ui/rm_node_modules.sh: -------------------------------------------------------------------------------- 1 | ROOT=$(pwd) 2 | 3 | PKGS=" 4 | $ROOT/../../web/corejs 5 | $ROOT/tiptap/tiptapjs 6 | $ROOT/vuetify/vuetifyjs 7 | $ROOT/docs/docsjs 8 | " 9 | for i in $PKGS 10 | do 11 | echo "$i/node_modules" && \ 12 | rm -rf $i/node_modules 13 | done 14 | -------------------------------------------------------------------------------- /ui/tiptap/build.sh: -------------------------------------------------------------------------------- 1 | # @snippet_begin(TiptapBuilderSH) 2 | CUR=$(pwd)/$(dirname $0) 3 | 4 | if test "$1" = 'clean'; then 5 | echo "Removing node_modules" 6 | rm -rf $CUR/tiptapjs/node_modules/ 7 | fi 8 | 9 | rm -r $CUR/tiptapjs/dist 10 | echo "Building tiptapjs" 11 | cd $CUR/tiptapjs && pnpm install && pnpm run build 12 | 13 | # @snippet_end 14 | -------------------------------------------------------------------------------- /ui/tiptap/tiptap.go: -------------------------------------------------------------------------------- 1 | package tiptap 2 | 3 | // @snippet_begin(TipTapEditorHTMLComponent) 4 | import ( 5 | "context" 6 | 7 | h "github.com/theplant/htmlgo" 8 | ) 9 | 10 | type TipTapEditorBuilder struct { 11 | tag *h.HTMLTagBuilder 12 | } 13 | 14 | func TipTapEditor() (r *TipTapEditorBuilder) { 15 | r = &TipTapEditorBuilder{ 16 | tag: h.Tag("tiptap-editor"), 17 | } 18 | 19 | return 20 | } 21 | 22 | func (b *TipTapEditorBuilder) Attr(vs ...interface{}) (r *TipTapEditorBuilder) { 23 | b.tag.Attr(vs...) 24 | return b 25 | } 26 | 27 | func (b *TipTapEditorBuilder) MarshalHTML(ctx context.Context) (r []byte, err error) { 28 | return b.tag.MarshalHTML(ctx) 29 | } 30 | 31 | // @snippet_end 32 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs.go: -------------------------------------------------------------------------------- 1 | package tiptap 2 | 3 | // @snippet_begin(TipTapPackrSample) 4 | import ( 5 | "embed" 6 | 7 | "github.com/qor5/web/v3" 8 | ) 9 | 10 | //go:embed tiptapjs/dist 11 | var box embed.FS 12 | 13 | func JSComponentsPack() web.ComponentsPack { 14 | v, err := box.ReadFile("tiptapjs/dist/tiptapjs.umd.cjs") 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | return web.ComponentsPack(v) 20 | } 21 | 22 | func CSSComponentsPack() web.ComponentsPack { 23 | v, err := box.ReadFile("tiptapjs/dist/tiptap.css") 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | return web.ComponentsPack(v) 29 | } 30 | 31 | // @snippet_end 32 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist-ssr 13 | coverage 14 | *.local 15 | 16 | /cypress/videos/ 17 | /cypress/screenshots/ 18 | 19 | # Editor directories and files 20 | .vscode/* 21 | !.vscode/extensions.json 22 | .idea 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | 29 | *.tsbuildinfo 30 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/README.md: -------------------------------------------------------------------------------- 1 | # tiptapjs 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). 8 | 9 | ## Type Support for `.vue` Imports in TS 10 | 11 | TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. 12 | 13 | ## Customize configuration 14 | 15 | See [Vite Configuration Reference](https://vitejs.dev/config/). 16 | 17 | ## Project Setup 18 | 19 | ```sh 20 | pnpm install 21 | ``` 22 | 23 | ### Compile and Hot-Reload for Development 24 | 25 | ```sh 26 | pnpm dev 27 | ``` 28 | 29 | ### Type-Check, Compile and Minify for Production 30 | 31 | ```sh 32 | pnpm build 33 | ``` 34 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/tiptap/tiptapjs/public/favicon.ico -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/demo/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/demo/components/EditorExample.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/demo/main.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * main.ts 3 | * 4 | * Bootstraps Vuetify and other plugins then mounts the App` 5 | */ 6 | 7 | // Plugins 8 | 9 | // Components 10 | import App from "@/demo/App.vue"; 11 | 12 | // Composables 13 | import { createApp } from "vue"; 14 | 15 | const app = createApp(App); 16 | app.mount("#app"); 17 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/demo/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "*.vue" { 4 | import type { DefineComponent } from "vue"; 5 | const component: DefineComponent<{}, {}, any>; 6 | export default component; 7 | } 8 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/Icon.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | 27 | 54 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/add_col_after.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/add_col_before.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/add_row_after.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/add_row_before.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/bold.svg: -------------------------------------------------------------------------------- 1 | text-bold 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/checklist.svg: -------------------------------------------------------------------------------- 1 | checklist-alternate 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/code.svg: -------------------------------------------------------------------------------- 1 | angle-brackets 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/combine_cells.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/delete_col.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/delete_row.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/hr.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/image.svg: -------------------------------------------------------------------------------- 1 | paginate-filter-picture-alternate 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/italic.svg: -------------------------------------------------------------------------------- 1 | text-italic 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/link.svg: -------------------------------------------------------------------------------- 1 | hyperlink-2 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/mention.svg: -------------------------------------------------------------------------------- 1 | read-email-at-alternate -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/ol.svg: -------------------------------------------------------------------------------- 1 | list-numbers 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/paragraph.svg: -------------------------------------------------------------------------------- 1 | paragraph 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/quote.svg: -------------------------------------------------------------------------------- 1 | close-quote 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/redo.svg: -------------------------------------------------------------------------------- 1 | redo 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/remove.svg: -------------------------------------------------------------------------------- 1 | delete-2-alternate 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/strike.svg: -------------------------------------------------------------------------------- 1 | text-strike-through 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/table.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/ul.svg: -------------------------------------------------------------------------------- 1 | list-bullets 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/underline.svg: -------------------------------------------------------------------------------- 1 | text-underline 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/icons/undo.svg: -------------------------------------------------------------------------------- 1 | undo 2 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/main.ts: -------------------------------------------------------------------------------- 1 | // @snippet_begin(TipTapRegisterVueComponent) 2 | import { type App } from "vue"; 3 | import TipTapEditor from "@/lib/Editor.vue"; 4 | 5 | declare const window: any; 6 | window.__goplaidVueComponentRegisters = 7 | window.__goplaidVueComponentRegisters || []; 8 | window.__goplaidVueComponentRegisters.push((app: App, vueOptions: any): any => { 9 | app.component("tiptap-editor", TipTapEditor); 10 | }); 11 | // @snippet_end 12 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import "./variables"; 2 | @import "./editor"; 3 | @import "./menubar"; 4 | @import "./menububble"; 5 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/sass/menubar.scss: -------------------------------------------------------------------------------- 1 | .menubar { 2 | margin-bottom: 1rem; 3 | transition: 4 | visibility 0.2s 0.4s, 5 | opacity 0.2s 0.4s; 6 | 7 | &.is-hidden { 8 | visibility: hidden; 9 | opacity: 0; 10 | } 11 | 12 | &.is-focused { 13 | visibility: visible; 14 | opacity: 1; 15 | transition: 16 | visibility 0.2s, 17 | opacity 0.2s; 18 | } 19 | 20 | &__button { 21 | font-weight: bold; 22 | display: inline-flex; 23 | background: transparent; 24 | border: 0; 25 | color: $color-black; 26 | padding: 0.2rem 0.5rem; 27 | margin-right: 0.2rem; 28 | border-radius: 3px; 29 | cursor: pointer; 30 | 31 | &:hover { 32 | background-color: rgba($color-black, 0.05); 33 | } 34 | 35 | &.is-active { 36 | background-color: rgba($color-black, 0.1); 37 | } 38 | } 39 | 40 | span#{&}__button { 41 | font-size: 13.3333px; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/sass/menububble.scss: -------------------------------------------------------------------------------- 1 | .menububble { 2 | position: absolute; 3 | display: flex; 4 | z-index: 20; 5 | background: $color-black; 6 | border-radius: 5px; 7 | padding: 0.3rem; 8 | margin-bottom: 0.5rem; 9 | transform: translateX(-50%); 10 | visibility: hidden; 11 | opacity: 0; 12 | transition: 13 | opacity 0.2s, 14 | visibility 0.2s; 15 | 16 | &.is-active { 17 | opacity: 1; 18 | visibility: visible; 19 | } 20 | 21 | &__button { 22 | display: inline-flex; 23 | background: transparent; 24 | border: 0; 25 | color: $color-white; 26 | padding: 0.2rem 0.5rem; 27 | margin-right: 0.2rem; 28 | border-radius: 3px; 29 | cursor: pointer; 30 | 31 | &:last-child { 32 | margin-right: 0; 33 | } 34 | 35 | &:hover { 36 | background-color: rgba($color-white, 0.1); 37 | } 38 | 39 | &.is-active { 40 | background-color: rgba($color-white, 0.2); 41 | } 42 | } 43 | 44 | &__form { 45 | display: flex; 46 | align-items: center; 47 | } 48 | 49 | &__input { 50 | font: inherit; 51 | border: none; 52 | background: transparent; 53 | color: $color-white; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/sass/variables.scss: -------------------------------------------------------------------------------- 1 | $color-black: #000000; 2 | $color-white: #ffffff; 3 | $color-grey: #dddddd; 4 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/src/lib/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "*.vue" { 4 | import type { DefineComponent } from "vue"; 5 | const component: DefineComponent<{}, {}, any>; 6 | export default component; 7 | } 8 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 | 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /ui/tiptap/tiptapjs/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "vitest.config.*", 6 | "cypress.config.*", 7 | "nightwatch.conf.*", 8 | "playwright.config.*" 9 | ], 10 | "compilerOptions": { 11 | "composite": true, 12 | "noEmit": true, 13 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 14 | 15 | "module": "ESNext", 16 | "moduleResolution": "Bundler", 17 | "types": ["node"] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ui/update_package_json.sh: -------------------------------------------------------------------------------- 1 | ROOT=$(pwd) 2 | 3 | PKGS=" 4 | $ROOT/../../web/corejs 5 | $ROOT/tiptap/tiptapjs 6 | $ROOT/vuetifyx/vuetifyxjs 7 | $ROOT/cropper/cropperjs 8 | $ROOT/redactor/redactorjs 9 | " 10 | for i in $PKGS 11 | do 12 | echo "$i" && \ 13 | cd $i && pnpm update && pnpm install && pnpm build 14 | done 15 | -------------------------------------------------------------------------------- /ui/vuetify/fix-autocomplete.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import ( 4 | h "github.com/theplant/htmlgo" 5 | ) 6 | 7 | func VAutocomplete(children ...h.HTMLComponent) (r *VAutocompleteBuilder) { 8 | r = &VAutocompleteBuilder{ 9 | tag: h.Tag("v-autocomplete").Children(children...), 10 | } 11 | return 12 | } 13 | 14 | func (b *VAutocompleteBuilder) ErrorMessages(v ...string) (r *VAutocompleteBuilder) { 15 | SetErrorMessages(b.tag, v) 16 | return b 17 | } 18 | -------------------------------------------------------------------------------- /ui/vuetify/fix-btn.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import ( 4 | "github.com/qor5/web/v3" 5 | h "github.com/theplant/htmlgo" 6 | ) 7 | 8 | func VBtn(text string) (r *VBtnBuilder) { 9 | r = &VBtnBuilder{ 10 | tag: h.Tag("v-btn").Text(text), 11 | } 12 | return 13 | } 14 | 15 | func (b *VBtnBuilder) OnClick(eventFuncId string) (r *VBtnBuilder) { 16 | b.tag.Attr("@click", web.POST().EventFunc(eventFuncId).Go()) 17 | return b 18 | } 19 | 20 | func (b *VBtnBuilder) AttrIf(key, value interface{}, add bool) (r *VBtnBuilder) { 21 | b.tag.AttrIf(key, value, add) 22 | return b 23 | } 24 | -------------------------------------------------------------------------------- /ui/vuetify/fix-checkbox.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VCheckboxBuilder) ErrorMessages(v ...string) (r *VCheckboxBuilder) { 4 | SetErrorMessages(b.tag, v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-chip-group.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VChipGroupBuilder) Value(v interface{}) (r *VChipGroupBuilder) { 4 | b.ModelValue(v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-container.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import "fmt" 4 | 5 | type DType string 6 | 7 | const ( 8 | DTypeFlex DType = "flex" 9 | DTypeInlineFlex DType = "inline-flex" 10 | DTypeBlock DType = "block" 11 | ) 12 | 13 | type SizeType string 14 | 15 | const ( 16 | Xs SizeType = "xs" 17 | Sm SizeType = "sm" 18 | Md SizeType = "md" 19 | Lg SizeType = "lg" 20 | Xl SizeType = "xl" 21 | ) 22 | 23 | type AlignType string 24 | 25 | const ( 26 | Left AlignType = "left" 27 | Center AlignType = "center" 28 | Right AlignType = "right" 29 | Justify AlignType = "justify" 30 | ) 31 | 32 | func (b *VContainerBuilder) DType(v DType) (r *VContainerBuilder) { 33 | b.tag.Attr(fmt.Sprintf(":d-%s", v), fmt.Sprint(true)) 34 | return b 35 | } 36 | 37 | func (b *VContainerBuilder) TextAlign(s SizeType, a AlignType) (r *VContainerBuilder) { 38 | b.tag.Attr(fmt.Sprintf(":text-%s-%s", s, a), fmt.Sprint(true)) 39 | return b 40 | } 41 | 42 | func (b *VLayoutBuilder) DType(v DType) (r *VLayoutBuilder) { 43 | b.tag.Attr(fmt.Sprintf(":d-%s", v), fmt.Sprint(true)) 44 | return b 45 | } 46 | 47 | func (b *VContainerBuilder) GridList(s SizeType) (r *VContainerBuilder) { 48 | b.tag.Attr(fmt.Sprintf(":grid-list-%s", s), fmt.Sprint(true)) 49 | return b 50 | } 51 | -------------------------------------------------------------------------------- /ui/vuetify/fix-file-input.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VFileInputBuilder) ErrorMessages(v ...string) (r *VFileInputBuilder) { 4 | SetErrorMessages(b.tag, v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-icon.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import h "github.com/theplant/htmlgo" 4 | 5 | func VIcon(name string) (r *VIconBuilder) { 6 | r = &VIconBuilder{tag: h.Tag("v-icon")} 7 | r.Icon(name) 8 | return 9 | } 10 | -------------------------------------------------------------------------------- /ui/vuetify/fix-list-item.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VListItemBuilder) Slot(v string) (r *VListItemBuilder) { 4 | b.tag.Attr("slot", v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-option-item.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | type DefaultOptionItem struct { 4 | Text string `json:"text"` 5 | Value string `json:"value"` 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-radio-group.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VRadioGroupBuilder) ErrorMessages(v ...string) (r *VRadioGroupBuilder) { 4 | SetErrorMessages(b.tag, v) 5 | return b 6 | } 7 | 8 | func (b *VRadioGroupBuilder) Value(v interface{}) (r *VRadioGroupBuilder) { 9 | b.ModelValue(v) 10 | return b 11 | } 12 | -------------------------------------------------------------------------------- /ui/vuetify/fix-select.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import ( 4 | h "github.com/theplant/htmlgo" 5 | ) 6 | 7 | func VSelect(children ...h.HTMLComponent) (r *VSelectBuilder) { 8 | r = &VSelectBuilder{ 9 | tag: h.Tag("v-select").Children(children...), 10 | } 11 | return 12 | } 13 | 14 | func (b *VSelectBuilder) ErrorMessages(v ...string) (r *VSelectBuilder) { 15 | SetErrorMessages(b.tag, v) 16 | return b 17 | } 18 | 19 | func (b *VSelectBuilder) Value(v interface{}) (r *VSelectBuilder) { 20 | b.ModelValue(v) 21 | return b 22 | } 23 | -------------------------------------------------------------------------------- /ui/vuetify/fix-slider.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VSliderBuilder) ErrorMessages(v ...string) (r *VSliderBuilder) { 4 | SetErrorMessages(b.tag, v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-switch.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VSwitchBuilder) ErrorMessages(v ...string) (r *VSwitchBuilder) { 4 | SetErrorMessages(b.tag, v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-table.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import h "github.com/theplant/htmlgo" 4 | 5 | func VTable(children ...h.HTMLComponent) (r *VTableBuilder) { 6 | r = &VTableBuilder{ 7 | tag: h.Tag("v-table").Children( 8 | h.Template( 9 | children..., 10 | ).Attr("#default", true), 11 | ), 12 | } 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /ui/vuetify/fix-text-field.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VTextFieldBuilder) ErrorMessages(v ...string) (r *VTextFieldBuilder) { 4 | SetErrorMessages(b.tag, v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-textarea.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VTextareaBuilder) ErrorMessages(v ...string) (r *VTextareaBuilder) { 4 | SetErrorMessages(b.tag, v) 5 | return b 6 | } 7 | -------------------------------------------------------------------------------- /ui/vuetify/fix-toolbar-title.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import h "github.com/theplant/htmlgo" 4 | 5 | func VToolbarTitle(text string) (r *VToolbarTitleBuilder) { 6 | r = &VToolbarTitleBuilder{ 7 | tag: h.Tag("v-toolbar-title").Text(text), 8 | } 9 | return 10 | } 11 | -------------------------------------------------------------------------------- /ui/vuetify/fix-toolbar.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | func (b *VToolbarBuilder) AutoHeight(v bool) (r *VToolbarBuilder) { 4 | if v { 5 | b.tag.Attr(":height", `"auto"`) 6 | } else { 7 | b.tag.Attr(":height", ``) 8 | } 9 | return b 10 | } 11 | -------------------------------------------------------------------------------- /ui/vuetify/fix-utils.go: -------------------------------------------------------------------------------- 1 | package vuetify 2 | 3 | import ( 4 | "strings" 5 | 6 | h "github.com/theplant/htmlgo" 7 | ) 8 | 9 | func stringsTrim(vs ...string) (r []string) { 10 | for _, v := range vs { 11 | if cv := strings.TrimSpace(v); len(cv) > 0 { 12 | r = append(r, cv) 13 | } 14 | } 15 | return 16 | } 17 | 18 | func SetErrorMessages(t h.MutableAttrHTMLComponent, vs []string) { 19 | cvs := stringsTrim(vs...) 20 | if len(cvs) == 0 { 21 | return 22 | } 23 | t.SetAttr(":error-messages", h.JSONString(cvs)) 24 | } 25 | -------------------------------------------------------------------------------- /ui/vuetify/gen_vuetify.sh: -------------------------------------------------------------------------------- 1 | API=/opt/homebrew/lib/node_modules/vuetify/dist/json/web-types.json 2 | npm -g install vuetify@3.6.14 3 | find *.go | grep -v "fix-" | xargs rm 4 | cat $API | vuetifyapi2go -comp=all 5 | -------------------------------------------------------------------------------- /ui/vuetifyx/build.sh: -------------------------------------------------------------------------------- 1 | CUR=$(pwd)/$(dirname $0) 2 | 3 | if test "$1" = 'clean'; then 4 | echo "Removing node_modules" 5 | rm -rf ./vuetifyxjs/node_modules/ 6 | fi 7 | 8 | rm -r $CUR/vuetifyxjs/dist 9 | echo "Building vuetifyjs" 10 | cd $CUR/vuetifyxjs && pnpm install && pnpm format && pnpm run build 11 | -------------------------------------------------------------------------------- /ui/vuetifyx/message-listener.go: -------------------------------------------------------------------------------- 1 | package vuetifyx 2 | 3 | import ( 4 | "context" 5 | 6 | h "github.com/theplant/htmlgo" 7 | ) 8 | 9 | type VXMessageListenerBuilder struct { 10 | tag *h.HTMLTagBuilder 11 | listenFunc string 12 | } 13 | 14 | func VXMessageListener() (r *VXMessageListenerBuilder) { 15 | r = &VXMessageListenerBuilder{ 16 | tag: h.Tag("vx-messagelistener"), 17 | } 18 | return 19 | } 20 | 21 | func (b *VXMessageListenerBuilder) ListenFunc(v string) (r *VXMessageListenerBuilder) { 22 | b.listenFunc = v 23 | return b 24 | } 25 | 26 | func (b *VXMessageListenerBuilder) MarshalHTML(ctx context.Context) (r []byte, err error) { 27 | if b.listenFunc != "" { 28 | b.tag.Attr(":listen-func", b.listenFunc) 29 | } 30 | 31 | return b.tag.MarshalHTML(ctx) 32 | } 33 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | not ie 11 5 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | 4 | # local env files 5 | .env.local 6 | .env.*.local 7 | 8 | # Log files 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | pnpm-debug.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | 23 | docs/.vitepress/cache/**/* 24 | docs/.vitepress/dist 25 | docs/.vitepress/.temp 26 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.eot -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.ttf -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.woff -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/dist/assets/materialdesignicons-webfont.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // theme/index.ts 2 | // import DefaultTheme from 'vitepress/theme'; 3 | import theme from './theme-default/theme.ts' 4 | import { registerComponents } from './register-components.ts' 5 | import { h } from 'vue' 6 | import myLayout from './myLayout' 7 | 8 | export default { 9 | // ...DefaultTheme, 10 | ...theme, 11 | Layout: () => { 12 | return h(myLayout) 13 | }, 14 | enhanceApp({app}) { 15 | registerComponents(app) 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/myLayout.ts: -------------------------------------------------------------------------------- 1 | import { defineComponent, h } from 'vue' 2 | import theme from './theme-default/theme' 3 | 4 | import './theme-default/custom.scss' 5 | const { Layout } = theme 6 | export default defineComponent({ 7 | async mounted() { 8 | // 黑暗模式设配 9 | // const { default: theme } = await import('../../../promiseui/theme') 10 | const toggleTheme = (isDark: boolean) => { 11 | // if (!isDark) { 12 | // theme.use('light') 13 | // } else { 14 | // theme.use('dark') 15 | // } 16 | } 17 | const observer = new MutationObserver((entries) => { 18 | entries.forEach((mutation) => { 19 | const target = mutation.target as HTMLHtmlElement 20 | toggleTheme(target.classList.contains('dark')) 21 | }) 22 | }) 23 | observer.observe(document.documentElement, { 24 | attributes: true, 25 | attributeFilter: ['class'] 26 | }) 27 | toggleTheme(document.documentElement.classList.contains('dark')) 28 | }, 29 | render() { 30 | return h(Layout) 31 | } 32 | }) 33 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/register-components.ts: -------------------------------------------------------------------------------- 1 | import { App } from 'vue' 2 | import DemoPreview, { useComponents } from '@vitepress-code-preview/container' 3 | import '@vitepress-code-preview/container/dist/style.css' 4 | import { registerPlugins } from '@/lib/plugins' 5 | 6 | export function registerComponents(app: App) { 7 | app.use(registerPlugins) 8 | useComponents(app, DemoPreview) 9 | } 10 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPBackdrop.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 42 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPDocAside.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | 47 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPDocAsideCarbonAds.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPDocAsideSponsors.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPHomeContent.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | 19 | 56 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPHomeFeatures.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPHomeHero.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 25 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPImage.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 38 | 39 | 47 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPLink.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 38 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPMenuGroup.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | 20 | 48 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPMenuLink.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 26 | 27 | 55 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavBarAppearance.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 33 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavBarMenu.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 29 | 30 | 41 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavBarMenuGroup.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 43 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavBarMenuLink.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 33 | 34 | 54 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavBarSocialLinks.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 28 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavBarTranslations.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 48 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavScreenAppearance.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 23 | 24 | 41 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavScreenMenu.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavScreenMenuGroupLink.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | 25 | 40 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavScreenMenuGroupSection.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | 22 | 35 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavScreenMenuLink.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 23 | 24 | 40 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPNavScreenSocialLinks.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPPage.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPSidebarGroup.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 39 | 40 | 57 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPSocialLink.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 27 | 28 | 51 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPSocialLinks.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | 22 | 28 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPSponsors.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 49 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPSponsorsGrid.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 49 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPSwitchAppearance.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 32 | 33 | 55 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPTeamPage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 59 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/VPTeamPageTitle.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 64 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconAlignJustify.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconAlignLeft.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconAlignRight.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconArrowLeft.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconArrowRight.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconChevronDown.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconChevronLeft.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconChevronRight.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconChevronUp.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconEdit.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconHeart.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconLanguages.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconMinus.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconMinusSquare.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconMoon.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconMoreHorizontal.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconPlus.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconPlusSquare.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/components/icons/VPIconSun.vue: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/composables/aside.js: -------------------------------------------------------------------------------- 1 | import { useMediaQuery } from '@vueuse/core'; 2 | import { computed } from 'vue'; 3 | import { useSidebar } from './sidebar'; 4 | export function useAside() { 5 | const { hasSidebar } = useSidebar(); 6 | const is960 = useMediaQuery('(min-width: 960px)'); 7 | const is1280 = useMediaQuery('(min-width: 1280px)'); 8 | const isAsideEnabled = computed(() => { 9 | if (!is1280.value && !is960.value) { 10 | return false; 11 | } 12 | return hasSidebar.value ? is1280.value : is960.value; 13 | }); 14 | return { 15 | isAsideEnabled 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/composables/data.js: -------------------------------------------------------------------------------- 1 | import { useData as useData$ } from 'vitepress'; 2 | export const useData = useData$; 3 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/composables/edit-link.js: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue'; 2 | import { useData } from './data'; 3 | export function useEditLink() { 4 | const { theme, page } = useData(); 5 | return computed(() => { 6 | const { text = 'Edit this page', pattern = '' } = theme.value.editLink || {}; 7 | let url; 8 | if (typeof pattern === 'function') { 9 | url = pattern(page.value); 10 | } 11 | else { 12 | url = pattern.replace(/:path/g, page.value.filePath); 13 | } 14 | return { url, text }; 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/composables/langs.js: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue'; 2 | import { ensureStartingSlash } from '../support/utils'; 3 | import { useData } from './data'; 4 | export function useLangs({ correspondingLink = false } = {}) { 5 | const { site, localeIndex, page, theme, hash } = useData(); 6 | const currentLang = computed(() => ({ 7 | label: site.value.locales[localeIndex.value]?.label, 8 | link: site.value.locales[localeIndex.value]?.link || 9 | (localeIndex.value === 'root' ? '/' : `/${localeIndex.value}/`) 10 | })); 11 | const localeLinks = computed(() => Object.entries(site.value.locales).flatMap(([key, value]) => currentLang.value.label === value.label 12 | ? [] 13 | : { 14 | text: value.label, 15 | link: normalizeLink(value.link || (key === 'root' ? '/' : `/${key}/`), theme.value.i18nRouting !== false && correspondingLink, page.value.relativePath.slice(currentLang.value.link.length - 1), !site.value.cleanUrls) + hash.value 16 | })); 17 | return { localeLinks, currentLang }; 18 | } 19 | function normalizeLink(link, addPath, path, addExt) { 20 | return addPath 21 | ? link.replace(/\/$/, '') + 22 | ensureStartingSlash(path 23 | .replace(/(^|\/)index\.md$/, '$1') 24 | .replace(/\.md$/, addExt ? '.html' : '')) 25 | : link; 26 | } 27 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/composables/local-nav.js: -------------------------------------------------------------------------------- 1 | import { onContentUpdated } from 'vitepress'; 2 | import { computed, shallowRef } from 'vue'; 3 | import { getHeaders } from '../composables/outline'; 4 | import { useData } from './data'; 5 | export function useLocalNav() { 6 | const { theme, frontmatter } = useData(); 7 | const headers = shallowRef([]); 8 | const hasLocalNav = computed(() => { 9 | return headers.value.length > 0; 10 | }); 11 | onContentUpdated(() => { 12 | headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline); 13 | }); 14 | return { 15 | headers, 16 | hasLocalNav 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/composables/nav.js: -------------------------------------------------------------------------------- 1 | import { ref, watch } from 'vue'; 2 | import { useRoute } from 'vitepress'; 3 | export function useNav() { 4 | const isScreenOpen = ref(false); 5 | function openScreen() { 6 | isScreenOpen.value = true; 7 | window.addEventListener('resize', closeScreenOnTabletWindow); 8 | } 9 | function closeScreen() { 10 | isScreenOpen.value = false; 11 | window.removeEventListener('resize', closeScreenOnTabletWindow); 12 | } 13 | function toggleScreen() { 14 | isScreenOpen.value ? closeScreen() : openScreen(); 15 | } 16 | /** 17 | * Close screen when the user resizes the window wider than tablet size. 18 | */ 19 | function closeScreenOnTabletWindow() { 20 | window.outerWidth >= 768 && closeScreen(); 21 | } 22 | const route = useRoute(); 23 | watch(() => route.path, closeScreen); 24 | return { 25 | isScreenOpen, 26 | openScreen, 27 | closeScreen, 28 | toggleScreen 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-cyrillic-ext.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-cyrillic-ext.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-cyrillic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-cyrillic.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-greek-ext.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-greek-ext.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-greek.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-greek.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-latin-ext.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-latin-ext.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-latin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-latin.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-vietnamese.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-italic-vietnamese.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-cyrillic-ext.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-cyrillic-ext.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-cyrillic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-cyrillic.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-greek-ext.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-greek-ext.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-greek.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-greek.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-latin-ext.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-latin-ext.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-latin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-latin.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-vietnamese.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/fonts/inter-roman-vietnamese.woff2 -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/index.js: -------------------------------------------------------------------------------- 1 | import './styles/fonts.css'; 2 | export * from '../without-fonts'; 3 | export { default as default } from '../without-fonts'; 4 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/styles/components/vp-code.css: -------------------------------------------------------------------------------- 1 | .dark .vp-code span { 2 | color: var(--shiki-dark, inherit); 3 | } 4 | 5 | html:not(.dark) .vp-code span { 6 | color: var(--shiki-light, inherit); 7 | } 8 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/styles/utils.css: -------------------------------------------------------------------------------- 1 | .visually-hidden { 2 | position: absolute; 3 | width: 1px; 4 | height: 1px; 5 | white-space: nowrap; 6 | clip: rect(0 0 0 0); 7 | clip-path: inset(50%); 8 | overflow: hidden; 9 | } 10 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/support/lru.js: -------------------------------------------------------------------------------- 1 | // adapted from https://stackoverflow.com/a/46432113/11613622 2 | export class LRUCache { 3 | max; 4 | cache; 5 | constructor(max = 10) { 6 | this.max = max; 7 | this.cache = new Map(); 8 | } 9 | get(key) { 10 | let item = this.cache.get(key); 11 | if (item !== undefined) { 12 | // refresh key 13 | this.cache.delete(key); 14 | this.cache.set(key, item); 15 | } 16 | return item; 17 | } 18 | set(key, val) { 19 | // refresh key 20 | if (this.cache.has(key)) 21 | this.cache.delete(key); 22 | // evict oldest 23 | else if (this.cache.size === this.max) 24 | this.cache.delete(this.first()); 25 | this.cache.set(key, val); 26 | } 27 | first() { 28 | return this.cache.keys().next().value; 29 | } 30 | clear() { 31 | this.cache.clear(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/support/utils.js: -------------------------------------------------------------------------------- 1 | import { withBase } from 'vitepress'; 2 | import { useData } from '../composables/data'; 3 | import { isExternal, treatAsHtml } from '../../shared'; 4 | export function throttleAndDebounce(fn, delay) { 5 | let timeoutId; 6 | let called = false; 7 | return () => { 8 | if (timeoutId) 9 | clearTimeout(timeoutId); 10 | if (!called) { 11 | fn(); 12 | (called = true) && setTimeout(() => (called = false), delay); 13 | } 14 | else 15 | timeoutId = setTimeout(fn, delay); 16 | }; 17 | } 18 | export function ensureStartingSlash(path) { 19 | return /^\//.test(path) ? path : `/${path}`; 20 | } 21 | export function normalizeLink(url) { 22 | const { pathname, search, hash, protocol } = new URL(url, 'http://a.com'); 23 | if (isExternal(url) || 24 | url.startsWith('#') || 25 | !protocol.startsWith('http') || 26 | !treatAsHtml(pathname)) 27 | return url; 28 | const { site } = useData(); 29 | const normalizedPath = pathname.endsWith('/') || pathname.endsWith('.html') 30 | ? url 31 | : url.replace(/(?:(^\.+)\/)?.*$/, `$1${pathname.replace(/(\.md)?$/, site.value.cleanUrls ? '' : '.html')}${search}${hash}`); 32 | return withBase(normalizedPath); 33 | } 34 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/.vitepress/theme/theme-default/theme.ts: -------------------------------------------------------------------------------- 1 | import './styles/icons.css' 2 | import './styles/fonts.css' 3 | import './styles/vars.css' 4 | import './styles/base.css' 5 | import './styles/utils.css' 6 | import './styles/components/custom-block.css' 7 | import './styles/components/vp-code.css' 8 | import './styles/components/vp-doc.css'; 9 | 10 | import './styles/components/vp-sponsor.css' 11 | import Layout from './Layout.vue' 12 | import NotFound from './NotFound.vue' 13 | export { default as VPHomeHero } from './components/VPHomeHero.vue' 14 | export { default as VPHomeFeatures } from './components/VPHomeFeatures.vue' 15 | export { default as VPHomeSponsors } from './components/VPHomeSponsors.vue' 16 | export { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue' 17 | export { default as VPTeamPage } from './components/VPTeamPage.vue' 18 | export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue' 19 | export { default as VPTeamPageSection } from './components/VPTeamPageSection.vue' 20 | export { default as VPTeamMembers } from './components/VPTeamMembers.vue' 21 | // make vue i18n happy 22 | if (typeof globalThis !== 'undefined') { 23 | globalThis.__VUE_PROD_DEVTOOLS__ = false; 24 | } else { 25 | window.__VUE_PROD_DEVTOOLS__ = false; 26 | } 27 | 28 | const theme = { 29 | Layout, 30 | NotFound 31 | } 32 | export default theme 33 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/Components/ScrollIframe/index.md: -------------------------------------------------------------------------------- 1 | # vx-scroll-iframe 输入框 2 | 3 | ## 基本用法 4 | 5 | :::demo 6 | 7 | ```vue 8 | 31 | 32 | 44 | 45 | 46 | 47 | 48 | ``` 49 | ::: -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/Components/VXField/sendVariables.md: -------------------------------------------------------------------------------- 1 | # vx-send-variables 输入框 2 | 3 | ## 基本用法 4 | 5 | :::demo 6 | 7 | ```vue 8 | 14 | 15 | 41 | 42 | ``` 43 | ::: -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/Components/VXModelConverter/index.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/Components/VXToolbar/index.md: -------------------------------------------------------------------------------- 1 | # vx-toolbar 2 | 3 | 这是一个基本示例,你可以用 `markdown` 语法 和 `vue3`、`vuetify` 在此处写任何组件代码 4 | 5 | ## 基本用法 6 | 7 | ```vue 8 | 9 | ``` 10 | 11 | :::demo 12 | 13 | ```vue 14 | 18 | ``` 19 | 20 | 21 | ::: -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | hero: 5 | name: VuetifyX 6 | text: 一个基于vuetify的企业级组件库 7 | # tagline: 主题可调,使用 TypeScript,交互式Demo 8 | actions: 9 | - theme: alt 10 | text: 快速开始 11 | link: /Components/VXField 12 | - theme: alt 13 | text: View on GitHub 14 | link: https://github.com/qor5/x/tree/master/ui/vuetifyx 15 | features: 16 | # - icon: 🔑 17 | # title: 使用 Typescript 18 | # details: 更好的代码提示 19 | # - icon: ⚡ 20 | # title: 按需引入 21 | # details: 支持按需引入 22 | # - icon: 🎁 23 | # title: 组件精美 24 | # details: 还算好看 25 | 26 | # - icon: 🌙 27 | # title: 黑暗模式 28 | # details: 支持黑暗模式 29 | # - icon: 🎨 30 | # title: 主题化 31 | # details: 支持自定义定制主题 32 | - icon: 🛠️ 33 | title: 交互式 34 | details: 组件文档采用交互式,可在线编辑实时 35 | --- 36 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | import { postcssIsolateStyles } from 'vitepress' 2 | 3 | export default { 4 | plugins: [postcssIsolateStyles({ 5 | includeFiles: [/vp-doc\.css/] 6 | })] 7 | } -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/public/imgs/vx-avatar-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/docs/public/imgs/vx-avatar-example.png -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { fileURLToPath, URL } from 'node:url' 3 | import { viteDemoPreviewPlugin } from '@vitepress-code-preview/plugin' 4 | import { UserConfig } from 'vitepress'; 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | viteDemoPreviewPlugin() 9 | ], 10 | resolve: { 11 | alias: { 12 | '@': fileURLToPath(new URL('../src', import.meta.url)) 13 | } 14 | } 15 | } as UserConfig) 16 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Welcome to Vuetify 3 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/patches/@vitepress-code-preview__container.patch: -------------------------------------------------------------------------------- 1 | diff --git a/dist/index.js b/dist/index.js 2 | index ab3dd78e9a373861d0265487fe1cd6ecc6d568ca..15d1733fc89c6e34623c5804387b8dad3d8ddf06 100644 3 | --- a/dist/index.js 4 | +++ b/dist/index.js 5 | @@ -1643,7 +1643,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({ 6 | }; 7 | } 8 | }); 9 | -const example = "_example_8jhae_2"; 10 | +const example = "_example_8jhae_2 vp-raw"; 11 | const style0 = { 12 | example, 13 | "example-showcase": "_example-showcase_8jhae_14", 14 | diff --git a/dist/index.umd.cjs b/dist/index.umd.cjs 15 | index f33062b5245d5a6ac6ff1db0af7ea0072631eb74..a4660855d149f7aa55f7370547cd535acc6130d6 100644 16 | --- a/dist/index.umd.cjs 17 | +++ b/dist/index.umd.cjs 18 | @@ -1646,7 +1646,7 @@ 19 | }; 20 | } 21 | }); 22 | - const example = "_example_8jhae_2"; 23 | + const example = "_example_8jhae_2 vp-raw"; 24 | const style0 = { 25 | example, 26 | "example-showcase": "_example-showcase_8jhae_14", 27 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qor5/x/e8fdf202ebcfb62a51cd5d9a83c761dfa36902e5/ui/vuetifyx/vuetifyxjs/public/favicon.ico -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Chart/useVxChartMergeOpts.ts: -------------------------------------------------------------------------------- 1 | import { ChartOptions } from './presets.config' 2 | 3 | export function useVxChartMergeOptsCallback(props: any) { 4 | const invokeMergeOptionsCallback = ( 5 | options: ChartOptions, 6 | mergeCallbackOptions: { seriesData: any[] } 7 | ) => { 8 | if (props.mergeOptionsCallback) { 9 | props.mergeOptionsCallback(options, mergeCallbackOptions) 10 | } 11 | } 12 | 13 | return { 14 | invokeMergeOptionsCallback 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Common/VXToolBar.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | 34 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/Constants.ts: -------------------------------------------------------------------------------- 1 | export const ModifierBetween = 'between' 2 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/AutoCompleteItem.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/DateItem.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/DatePickerItem.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/DateRangePickerItem.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/DatetimeRangePickerItem.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/FilterButton.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/LinkageSelectItem.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/LinkageSelectItemRemote.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/MultipleSelectItem.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Filter/components/SelectItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Form/VXSegmentForm/type.d.ts: -------------------------------------------------------------------------------- 1 | export type ConditionType = 'intersect' | 'union' 2 | 3 | export type TagType = { 4 | tag: { 5 | builderID: string 6 | params: Record 7 | values: string[] 8 | } 9 | } 10 | 11 | export type ConditionItemType = 12 | | TagType 13 | | { 14 | [key in ConditionType]?: ConditionItemType[] 15 | } 16 | 17 | export type SavedFormType = { 18 | [key in ConditionType]?: ConditionItemType[] 19 | } 20 | 21 | export type OptionsType = { 22 | id: string 23 | name: string 24 | description: string 25 | builders: BuilderType[] 26 | } 27 | 28 | export type BuilderType = { 29 | id: string 30 | name: string 31 | description: string 32 | categoryID: string 33 | view: ViewType 34 | } 35 | 36 | export type ViewType = { 37 | fragments: FragmentType[] 38 | } 39 | 40 | export type FragmentType = { 41 | defaultValue: string 42 | key: string 43 | multiple: boolean 44 | options: OptionType[] 45 | required: boolean 46 | skipIf: null | SkipType 47 | skipUnless: null | SkipType 48 | type: 'SELECT' | 'DATE_PICKER' | 'NUMBER' | 'NUMBER_INPUT' | 'TEXT' 49 | validation: null | string 50 | } 51 | 52 | export type SkipType = { 53 | [`$${string & K}`]: { 54 | [key: string]: string[] 55 | } 56 | } 57 | 58 | export type OptionType = { 59 | label: string 60 | value: string 61 | } 62 | -------------------------------------------------------------------------------- /ui/vuetifyx/vuetifyxjs/src/lib/Helpers.tsx: -------------------------------------------------------------------------------- 1 | import { VNode, h } from 'vue' 2 | 3 | export const Core = { 4 | props: { 5 | fieldName: String, 6 | loadPageWithArrayOp: Boolean 7 | } 8 | } 9 | 10 | export const SelectedItems = { 11 | props: { 12 | selectedItems: { 13 | type: Array, 14 | default: () => [] 15 | } as any, 16 | multiple: Boolean 17 | } 18 | } 19 | 20 | interface Slots { 21 | [key: string]: VNode[] | undefined 22 | } 23 | 24 | export const slotTemplates = (slots: Slots): VNode[] => { 25 | const templates: VNode[] = [] 26 | 27 | for (const name in slots) { 28 | if (!Object.getOwnPropertyDescriptor(slots, name)) { 29 | continue 30 | } 31 | templates.push(h('