├── .editorconfig ├── .github ├── contributing │ ├── oxford-comma.jpg │ └── writing-guide.md ├── dependabot.yml ├── pull_request_template.md ├── scripts │ └── tag-alert-blocks.js └── workflows │ └── automerge.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vitepress ├── config.ts ├── headerMdPlugin.ts ├── inlined-scripts │ ├── gtag.js │ ├── perfops.js │ ├── restorePreference.js │ └── uwu.js ├── textAdMdPlugin.ts └── theme │ ├── components │ ├── Banner.vue │ ├── CallToActionSection.vue │ ├── CardList.vue │ ├── Home.vue │ ├── NewsLetter.vue │ ├── PageHero.vue │ ├── PageShowcaseListLayout.vue │ ├── PreferenceSwitch.vue │ ├── PreferenceTooltip.vue │ ├── ReplLoading.vue │ ├── SecurityUpdateBtn.vue │ ├── SiteMap.vue │ ├── SponsorsAside.vue │ ├── SponsorsGroup.vue │ ├── TextAd.vue │ ├── VueJobs.vue │ ├── VueMasteryModal.vue │ ├── VueSchoolLink.vue │ ├── preferences.ts │ └── sponsors.ts │ ├── index.ts │ └── styles │ ├── badges.css │ ├── index.css │ ├── inline-demo.css │ ├── options-boxes.css │ ├── pages.css │ ├── style-guide.css │ ├── utilities.css │ └── vue-mastery.css ├── LICENSE ├── README.md ├── env.d.ts ├── netlify.toml ├── package.json ├── pnpm-lock.yaml ├── src ├── about │ ├── coc.md │ ├── community-guide.md │ ├── faq.md │ ├── images │ │ ├── ben-hong.jpeg │ │ └── evan-you.jpeg │ ├── privacy.md │ ├── releases.md │ ├── team.md │ └── team │ │ ├── Member.ts │ │ ├── TeamHero.vue │ │ ├── TeamList.vue │ │ ├── TeamMember.vue │ │ ├── TeamPage.vue │ │ ├── members-core.json │ │ ├── members-emeriti.json │ │ └── members-partner.json ├── api │ ├── ApiIndex.vue │ ├── api.data.ts │ ├── application.md │ ├── built-in-components.md │ ├── built-in-directives.md │ ├── built-in-special-attributes.md │ ├── built-in-special-elements.md │ ├── compile-time-flags.md │ ├── component-instance.md │ ├── composition-api-dependency-injection.md │ ├── composition-api-helpers.md │ ├── composition-api-lifecycle.md │ ├── composition-api-setup.md │ ├── custom-elements.md │ ├── custom-renderer.md │ ├── general.md │ ├── index.md │ ├── options-composition.md │ ├── options-lifecycle.md │ ├── options-misc.md │ ├── options-rendering.md │ ├── options-state.md │ ├── reactivity-advanced.md │ ├── reactivity-core.md │ ├── reactivity-utilities.md │ ├── render-function.md │ ├── sfc-css-features.md │ ├── sfc-script-setup.md │ ├── sfc-spec.md │ ├── ssr.md │ └── utility-types.md ├── developers │ ├── [developerSlug].md │ ├── [developerSlug].paths.ts │ ├── components │ │ ├── DeveloperCard.vue │ │ ├── DeveloperCompensations.vue │ │ ├── DeveloperEducation.vue │ │ ├── DeveloperExperiences.vue │ │ ├── DeveloperHero.vue │ │ ├── DeveloperImage.vue │ │ ├── DeveloperJoin.vue │ │ ├── DeveloperLanding.vue │ │ ├── DeveloperPage.vue │ │ ├── DeveloperPageFooter.vue │ │ ├── DeveloperProficiencies.vue │ │ ├── DeveloperProfileDiagram.vue │ │ ├── type.ts │ │ └── utils.ts │ ├── developers.json │ ├── index.md │ └── partnerConfig.js ├── ecosystem │ ├── newsletters.md │ ├── themes.md │ └── themes │ │ ├── ThemeContact.vue │ │ ├── ThemeHero.vue │ │ ├── ThemeList.vue │ │ ├── ThemeListItem.vue │ │ ├── ThemePage.vue │ │ ├── ThemeProduct.vue │ │ └── themes.json ├── error-reference │ ├── ErrorsTable.vue │ ├── errors.data.ts │ └── index.md ├── examples │ ├── ExampleRepl.vue │ ├── examples.data.ts │ ├── index.md │ ├── src │ │ ├── attribute-bindings │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── cells │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ ├── Cell │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ ├── description.txt │ │ │ └── store.js │ │ ├── circle-drawer │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── conditionals-and-loops │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── counter │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── crud │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── fetching-data │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── flight-booker │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── form-bindings │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── grid │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ ├── Grid │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── handling-input │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── hello-world │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── list-transition │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ ├── description.txt │ │ │ └── import-map.json │ │ ├── markdown │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ ├── description.txt │ │ │ └── import-map.json │ │ ├── modal │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ ├── Modal │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── simple-component │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ ├── TodoItem │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── svg │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ ├── AxisLabel │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ ├── PolyGraph │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ ├── description.txt │ │ │ └── util.js │ │ ├── temperature-converter │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ │ └── description.txt │ │ ├── timer │ │ │ ├── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ ├── style.css │ │ │ │ └── template.html │ │ │ └── description.txt │ │ └── tree │ │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ ├── style.css │ │ │ └── template.html │ │ │ ├── TreeItem │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ │ └── description.txt │ └── utils.ts ├── glossary │ └── index.md ├── guide │ ├── best-practices │ │ ├── accessibility.md │ │ ├── images │ │ │ ├── AccessibilityChromeDeveloperTools.png │ │ │ ├── AccessibleARIAdescribedby.png │ │ │ ├── AccessibleARIAlabelDevTools.png │ │ │ ├── AccessibleARIAlabelledbyDevTools.png │ │ │ ├── AccessibleLabelChromeDevTools.png │ │ │ └── AccessiblePlaceholder.png │ │ ├── performance.md │ │ ├── production-deployment.md │ │ └── security.md │ ├── built-ins │ │ ├── images │ │ │ └── transition-classes.png │ │ ├── keep-alive-demos │ │ │ ├── CompA.vue │ │ │ ├── CompB.vue │ │ │ └── SwitchComponent.vue │ │ ├── keep-alive.md │ │ ├── suspense.md │ │ ├── teleport.md │ │ ├── transition-demos │ │ │ ├── Basic.vue │ │ │ ├── BetweenComponents.vue │ │ │ ├── BetweenElements.vue │ │ │ ├── CssAnimation.vue │ │ │ ├── JsHooks.vue │ │ │ ├── ListBasic.vue │ │ │ ├── ListMove.vue │ │ │ ├── ListStagger.vue │ │ │ ├── NestedTransitions.vue │ │ │ └── SlideFade.vue │ │ ├── transition-group.md │ │ └── transition.md │ ├── components │ │ ├── async.md │ │ ├── attrs.md │ │ ├── events.md │ │ ├── images │ │ │ ├── named-slots.png │ │ │ ├── prop-drilling.png │ │ │ ├── provide-inject.png │ │ │ ├── scoped-slots.svg │ │ │ └── slots.png │ │ ├── props.md │ │ ├── provide-inject.md │ │ ├── registration.md │ │ ├── slots.md │ │ └── v-model.md │ ├── essentials │ │ ├── application.md │ │ ├── class-and-style.md │ │ ├── component-basics.md │ │ ├── computed.md │ │ ├── conditional.md │ │ ├── event-handling.md │ │ ├── forms.md │ │ ├── images │ │ │ ├── components.png │ │ │ ├── directive.png │ │ │ └── lifecycle.png │ │ ├── lifecycle.md │ │ ├── list.md │ │ ├── reactivity-fundamentals.md │ │ ├── template-refs.md │ │ ├── template-syntax.md │ │ └── watchers.md │ ├── extras │ │ ├── animation.md │ │ ├── composition-api-faq.md │ │ ├── demos │ │ │ ├── AnimateWatcher.vue │ │ │ ├── Colors.vue │ │ │ ├── DisabledButton.vue │ │ │ ├── ElasticHeader.vue │ │ │ ├── SpreadSheet.vue │ │ │ ├── SpreadSheetCell.vue │ │ │ └── spreadSheetStore.js │ │ ├── images │ │ │ ├── composition-api-after.png │ │ │ ├── options-api.png │ │ │ └── render-pipeline.png │ │ ├── reactivity-in-depth.md │ │ ├── reactivity-transform.md │ │ ├── render-function.md │ │ ├── rendering-mechanism.md │ │ ├── ways-of-using-vue.md │ │ └── web-components.md │ ├── introduction.md │ ├── quick-start.md │ ├── reusability │ │ ├── composables.md │ │ ├── custom-directives.md │ │ ├── mouse.js │ │ └── plugins.md │ ├── scaling-up │ │ ├── images │ │ │ ├── devtools.png │ │ │ └── state-flow.png │ │ ├── routing.md │ │ ├── sfc.md │ │ ├── ssr.md │ │ ├── state-management.md │ │ ├── testing.md │ │ └── tooling.md │ └── typescript │ │ ├── composition-api.md │ │ ├── options-api.md │ │ └── overview.md ├── index.md ├── partners │ ├── [partnerId].md │ ├── [partnerId].paths.ts │ ├── all.md │ ├── components │ │ ├── PartnerAll.vue │ │ ├── PartnerCard.vue │ │ ├── PartnerHero.vue │ │ ├── PartnerJoin.vue │ │ ├── PartnerLanding.vue │ │ ├── PartnerList.vue │ │ ├── PartnerLocation.vue │ │ ├── PartnerPage.vue │ │ ├── type.ts │ │ └── utils.ts │ ├── index.md │ └── partners.json ├── public │ ├── _headers │ ├── _redirects │ ├── funding.json │ ├── images │ │ ├── developers │ │ │ ├── 1020-profile.svg │ │ │ ├── 1020-score.svg │ │ │ ├── 1346-profile.svg │ │ │ ├── 1346-score.svg │ │ │ ├── 2030-profile.svg │ │ │ ├── 2030-score.svg │ │ │ ├── 2535-profile.svg │ │ │ ├── 2535-score.svg │ │ │ ├── 3021-profile.svg │ │ │ ├── 3021-score.svg │ │ │ ├── 3709-profile.svg │ │ │ ├── 3709-score.svg │ │ │ ├── 4290-profile.svg │ │ │ ├── 4290-score.svg │ │ │ ├── 5022-profile.svg │ │ │ ├── 5022-score.svg │ │ │ ├── 5328-profile.svg │ │ │ ├── 5328-score.svg │ │ │ ├── 5697-profile.svg │ │ │ └── 5697-score.svg │ │ ├── lambdatest.svg │ │ ├── logo.png │ │ ├── partners │ │ │ ├── 64robots-hero.jpg │ │ │ ├── 64robots.svg │ │ │ ├── curotec-hero.jpg │ │ │ ├── curotec.png │ │ │ ├── epicmax.png │ │ │ ├── epicmax.svg │ │ │ ├── herodevs-dark.png │ │ │ ├── herodevs-hero.png │ │ │ ├── herodevs.png │ │ │ ├── jump24-dark.svg │ │ │ ├── jump24-hero.jpg │ │ │ ├── jump24.svg │ │ │ ├── monterail-dark.png │ │ │ ├── monterail-hero.png │ │ │ ├── monterail.png │ │ │ ├── passionatepeople-dark.png │ │ │ ├── passionatepeople-hero.jpg │ │ │ ├── passionatepeople.png │ │ │ ├── proxify-dark.svg │ │ │ ├── proxify-hero.jpg │ │ │ ├── proxify.svg │ │ │ ├── redberry-hero.jpg │ │ │ ├── redberry.png │ │ │ ├── tighten-dark.svg │ │ │ ├── tighten-hero.jpg │ │ │ ├── tighten.svg │ │ │ ├── vehikl-dark.svg │ │ │ ├── vehikl-hero.jpg │ │ │ ├── vehikl.svg │ │ │ ├── webreinvent-hero.jpg │ │ │ └── webreinvent.png │ │ └── paypal.png │ ├── logo-uwu.png │ ├── logo.svg │ ├── rom3.min.js │ └── service-worker.js ├── sponsor │ └── index.md ├── style-guide │ ├── index.md │ ├── rules-essential.md │ ├── rules-recommended.md │ ├── rules-strongly-recommended.md │ └── rules-use-with-caution.md ├── translations │ └── index.md └── tutorial │ ├── TutorialRepl.vue │ ├── index.md │ ├── src │ ├── step-1 │ │ ├── App │ │ │ └── template.html │ │ └── description.md │ ├── step-10 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ └── options.js │ │ └── description.md │ ├── step-11 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── ChildComp │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ └── description.md │ ├── step-12 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── ChildComp │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ └── template.html │ │ └── description.md │ ├── step-13 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── ChildComp │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ └── template.html │ │ └── description.md │ ├── step-14 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── ChildComp │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ └── template.html │ │ └── description.md │ ├── step-15 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ ├── style.css │ │ │ └── template.html │ │ ├── description.md │ │ └── import-map.json │ ├── step-2 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ └── description.md │ ├── step-3 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ ├── style.css │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ └── template.html │ │ └── description.md │ ├── step-4 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ └── description.md │ ├── step-5 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ └── description.md │ ├── step-6 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ └── description.md │ ├── step-7 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ └── options.js │ │ └── description.md │ ├── step-8 │ │ ├── App │ │ │ ├── composition.js │ │ │ ├── options.js │ │ │ ├── style.css │ │ │ └── template.html │ │ ├── _hint │ │ │ └── App │ │ │ │ ├── composition.js │ │ │ │ ├── options.js │ │ │ │ └── template.html │ │ └── description.md │ └── step-9 │ │ ├── App │ │ ├── composition.js │ │ ├── options.js │ │ └── template.html │ │ ├── _hint │ │ └── App │ │ │ ├── composition.js │ │ │ └── options.js │ │ └── description.md │ └── tutorial.data.ts ├── tsconfig.json └── vercel.json /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | indent_style = space 4 | indent_size = 2 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.md] 10 | trim_trailing_whitespace = false 11 | -------------------------------------------------------------------------------- /.github/contributing/oxford-comma.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/.github/contributing/oxford-comma.jpg -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Enable version updates for npm 4 | - package-ecosystem: 'npm' 5 | # Look for `package.json` and `lock` files in the `root` directory 6 | directory: '/' 7 | # Check the npm registry for updates every day (weekdays) 8 | schedule: 9 | interval: 'daily' 10 | open-pull-requests-limit: 10 11 | versioning-strategy: lockfile-only 12 | allow: 13 | - dependency-name: 'vue' 14 | - dependency-name: 'vitepress' 15 | - dependency-name: '@vue/theme' 16 | - dependency-name: '@vue/repl' 17 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description of Problem 2 | 3 | ## Proposed Solution 4 | 5 | ## Additional Information 6 | -------------------------------------------------------------------------------- /.github/scripts/tag-alert-blocks.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { exec } = require('child_process') 4 | 5 | /** 6 | * Execute a command and return stdout as string. 7 | * @param {string} command 8 | * @returns {Promise} 9 | */ 10 | function run(command) { 11 | return new Promise((resolve, reject) => { 12 | exec(command, { encoding: 'utf-8' }, (error, stdout) => 13 | error ? reject(error) : resolve(stdout) 14 | ) 15 | }) 16 | } 17 | 18 | const ALERT_BLOCK = /^\+\s*:::\s?(\w+)/m 19 | 20 | async function isUsingAlertBlock(base = 'origin/master') { 21 | const result = await run(`git diff --name-only ${base}`) 22 | const files = ( 23 | await Promise.all( 24 | result 25 | .trim() 26 | .split(/\r?\n/) 27 | .map(file => 28 | run(`git diff ${base} -- ${file}`) 29 | .then(diff => ALERT_BLOCK.test(diff)) 30 | .then(usesAlertBlock => (usesAlertBlock ? file : '')) 31 | ) 32 | ) 33 | ).filter(Boolean) 34 | 35 | if (files.length) { 36 | return true 37 | } 38 | 39 | return false 40 | } 41 | 42 | module.exports = { isUsingAlertBlock } 43 | -------------------------------------------------------------------------------- /.github/workflows/automerge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | on: pull_request 3 | 4 | permissions: 5 | pull-requests: write 6 | contents: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: ${{ github.actor == 'dependabot[bot]' }} 12 | steps: 13 | - name: Dependabot metadata 14 | id: metadata 15 | uses: dependabot/fetch-metadata@v1.1.1 16 | with: 17 | github-token: '${{ secrets.GITHUB_TOKEN }}' 18 | - name: Enable auto-merge for theme 19 | if: ${{contains(steps.metadata.outputs.dependency-names, '@vue/theme') && steps.metadata.outputs.update-type != 'version-update:semver-major'}} 20 | run: gh pr merge --auto --merge "$PR_URL" 21 | env: 22 | PR_URL: ${{github.event.pull_request.html_url}} 23 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 24 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-manager-strict=false 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.vue 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 75 6 | } 7 | -------------------------------------------------------------------------------- /.vitepress/headerMdPlugin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A markdown-it plugin to support custom header metadata 3 | * Headers that end with * are Options API only 4 | * Headers that end with ** are Composition API only 5 | * This plugin strips the markers and augments the extracted header data, 6 | * which can be then used by the theme to filter headers. 7 | * 8 | * TODO: we will likely also need special syntax for preserving the same anchor 9 | * links across translations similar to the one at 10 | * https://github.com/vitejs/docs-cn/tree/main/.vitepress/markdown-it-custom-anchor 11 | */ 12 | 13 | import MarkdownIt from 'markdown-it' 14 | import { Header } from 'vitepress' 15 | 16 | export interface AugmentedHeader extends Header { 17 | compositionOnly?: boolean 18 | optionsOnly?: boolean 19 | } 20 | 21 | export const headerPlugin = (md: MarkdownIt) => { 22 | md.renderer.rules.heading_open = (tokens, i, options, env, self) => { 23 | for (const child of tokens[i + 1].children!) { 24 | if (child.type === 'text' && child.content.endsWith('*')) { 25 | child.content = child.content.replace(/\s*\*+$/, '') 26 | } 27 | } 28 | return self.renderToken(tokens, i, options) 29 | } 30 | 31 | const render = md.render 32 | md.render = (content, env) => { 33 | const res = render(content, env) 34 | 35 | if (env && env.headers) { 36 | processHeaders(env.headers) 37 | } 38 | 39 | return res 40 | } 41 | } 42 | 43 | function processHeaders(headers: AugmentedHeader[]) { 44 | for (const h of headers) { 45 | if (h.title.endsWith('*')) { 46 | if (h.title.endsWith('**')) { 47 | h.compositionOnly = true 48 | } else { 49 | h.optionsOnly = true 50 | } 51 | h.title = h.title.replace(/\s*\*+$/, '') 52 | } 53 | if (h.children) { 54 | processHeaders(h.children) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.vitepress/inlined-scripts/gtag.js: -------------------------------------------------------------------------------- 1 | ; (() => { 2 | window.dataLayer = window.dataLayer || [] 3 | function gtag() { dataLayer.push(arguments) } 4 | gtag('js', new Date()) 5 | 6 | gtag('config', 'G-45DMD2J2W8') 7 | })() -------------------------------------------------------------------------------- /.vitepress/inlined-scripts/perfops.js: -------------------------------------------------------------------------------- 1 | ;((d) => { 2 | window.rum = { key: 'a9efvfeu' } 3 | var script = d.createElement('script') 4 | script.src = '/rom3.min.js' 5 | script.type = 'text/javascript' 6 | script.defer = true 7 | script.async = true 8 | d.getElementsByTagName('head')[0].appendChild(script) 9 | })(document) 10 | -------------------------------------------------------------------------------- /.vitepress/inlined-scripts/restorePreference.js: -------------------------------------------------------------------------------- 1 | ;(() => { 2 | const restore = (key, cls, def = false) => { 3 | const saved = localStorage.getItem(key) 4 | if (saved ? saved !== 'false' : def) { 5 | document.documentElement.classList.add(cls) 6 | } 7 | } 8 | restore('vue-docs-prefer-composition', 'prefer-composition', true) 9 | restore('vue-docs-prefer-sfc', 'prefer-sfc', true) 10 | 11 | window.__VUE_BANNER_ID__ = 'vueconf2025' 12 | restore(`vue-docs-banner-${__VUE_BANNER_ID__}`, 'banner-dismissed') 13 | })() 14 | -------------------------------------------------------------------------------- /.vitepress/inlined-scripts/uwu.js: -------------------------------------------------------------------------------- 1 | if (location.search.includes('?uwu')) { 2 | document.documentElement.classList.add('uwu') 3 | } 4 | -------------------------------------------------------------------------------- /.vitepress/textAdMdPlugin.ts: -------------------------------------------------------------------------------- 1 | import MarkdownIt from 'markdown-it' 2 | 3 | const excludedPages = [ 4 | 'guide/introduction.md', 5 | // 'guide/quick-start.md', 6 | // 'guide/essentials/computed.md', 7 | // 'guide/essentials/conditional.md', 8 | // 'guide/essentials/list.md', 9 | // 'guide/essentials/event-handling.md', 10 | // 'guide/essentials/forms.md', 11 | // 'guide/components/registration.md', 12 | // 'guide/components/props.md', 13 | // 'guide/components/events.md', 14 | // 'guide/components/slots.md', 15 | // 'guide/built-ins/teleport.md', 16 | 'about/faq.md', 17 | 'about/team.md', 18 | 'about/releases.md', 19 | 'about/community-guide.md', 20 | 'about/coc.md', 21 | 'sponsor/index.md', 22 | 'translations/index.md' 23 | ] 24 | 25 | export const textAdPlugin = (md: MarkdownIt) => { 26 | md.renderer.rules.heading_close = (tokens, i, options, env, self) => { 27 | const relativePath = env.relativePath 28 | const renderedContent = self.renderToken(tokens, i, options) 29 | 30 | return excludedPages.includes(relativePath) 31 | ? renderedContent 32 | : renderedContent.replace(/<\/h1>/, '') 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.vitepress/theme/components/CallToActionSection.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | 25 | 74 | -------------------------------------------------------------------------------- /.vitepress/theme/components/PageHero.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 64 | -------------------------------------------------------------------------------- /.vitepress/theme/components/ReplLoading.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 60 | -------------------------------------------------------------------------------- /.vitepress/theme/components/SiteMap.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 27 | 28 | 68 | -------------------------------------------------------------------------------- /.vitepress/theme/components/SponsorsAside.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 26 | -------------------------------------------------------------------------------- /.vitepress/theme/components/TextAd.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 54 | -------------------------------------------------------------------------------- /.vitepress/theme/components/VueSchoolLink.vue: -------------------------------------------------------------------------------- 1 | 13 | 21 | 60 | -------------------------------------------------------------------------------- /.vitepress/theme/components/preferences.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | import { AugmentedHeader } from '../../headerMdPlugin' 3 | 4 | export const inBrowser = typeof window !== 'undefined' 5 | const get = (key: string, defaultValue = false): boolean => 6 | inBrowser 7 | ? JSON.parse(localStorage.getItem(key) || String(defaultValue)) 8 | : defaultValue 9 | 10 | export const preferCompositionKey = 'vue-docs-prefer-composition' 11 | export const preferComposition = ref(get(preferCompositionKey, true)) 12 | 13 | export const preferSFCKey = 'vue-docs-prefer-sfc' 14 | export const preferSFC = ref(get(preferSFCKey, true)) 15 | 16 | export function filterHeadersByPreference(h: AugmentedHeader) { 17 | return preferComposition.value ? !h.optionsOnly : !h.compositionOnly 18 | } 19 | -------------------------------------------------------------------------------- /.vitepress/theme/components/sponsors.ts: -------------------------------------------------------------------------------- 1 | // shared data across instances so we load only once 2 | 3 | import { ref } from 'vue' 4 | 5 | declare global { 6 | const fathom: { 7 | trackGoal: (id: string, value: number) => any 8 | } 9 | } 10 | 11 | export interface Sponsor { 12 | url: string 13 | img: string 14 | name: string 15 | description?: string 16 | priority?: boolean 17 | } 18 | 19 | export interface SponsorData { 20 | special: Sponsor[] 21 | platinum: Sponsor[] 22 | platinum_china: Sponsor[] 23 | gold: Sponsor[] 24 | silver: Sponsor[] 25 | bronze: Sponsor[] 26 | } 27 | 28 | export const data = ref() 29 | export const pending = ref(false) 30 | 31 | export const base = `https://sponsors.vuejs.org` 32 | 33 | export const load = async () => { 34 | if (!pending.value) { 35 | pending.value = true 36 | data.value = await (await fetch(`${base}/data.json`)).json() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import './styles/index.css' 2 | import { h, App } from 'vue' 3 | import { VPTheme } from '@vue/theme' 4 | import PreferenceSwitch from './components/PreferenceSwitch.vue' 5 | import SecurityUpdateBtn from './components/SecurityUpdateBtn.vue' 6 | import { 7 | preferComposition, 8 | preferSFC, 9 | filterHeadersByPreference 10 | } from './components/preferences' 11 | import SponsorsAside from './components/SponsorsAside.vue' 12 | import VueSchoolLink from './components/VueSchoolLink.vue' 13 | import Banner from './components/Banner.vue' 14 | // import TextAd from './components/TextAd.vue' 15 | 16 | export default Object.assign({}, VPTheme, { 17 | Layout: () => { 18 | // @ts-ignore 19 | return h(VPTheme.Layout, null, { 20 | banner: () => h(Banner), 21 | 'sidebar-top': () => h(PreferenceSwitch), 22 | 'sidebar-bottom': () => h(SecurityUpdateBtn), 23 | 'aside-mid': () => h(SponsorsAside) 24 | }) 25 | }, 26 | enhanceApp({ app }: { app: App }) { 27 | app.provide('prefer-composition', preferComposition) 28 | app.provide('prefer-sfc', preferSFC) 29 | app.provide('filter-headers', filterHeadersByPreference) 30 | app.component('VueSchoolLink', VueSchoolLink) 31 | // app.component('TextAd', TextAd) 32 | } 33 | }) 34 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/badges.css: -------------------------------------------------------------------------------- 1 | .vt-badge.wip:before { 2 | content: 'WIP'; 3 | } 4 | 5 | .vt-badge.ts { 6 | background-color: #3178c6; 7 | } 8 | .vt-badge.ts:before { 9 | content: 'TS'; 10 | } 11 | 12 | .vt-badge.dev-only, 13 | .vt-badge.experimental { 14 | color: var(--vt-c-text-light-1); 15 | background-color: var(--vt-c-yellow); 16 | } 17 | 18 | .vt-badge.dev-only:before { 19 | content: 'Dev only'; 20 | } 21 | 22 | .vt-badge.experimental:before { 23 | content: 'Experimental'; 24 | } 25 | 26 | .vt-badge[data-text]:before { 27 | content: attr(data-text); 28 | } 29 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/index.css: -------------------------------------------------------------------------------- 1 | @import "./pages.css"; 2 | @import "./badges.css"; 3 | @import "./options-boxes.css"; 4 | @import "./inline-demo.css"; 5 | @import "./utilities.css"; 6 | @import "./style-guide.css"; 7 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/options-boxes.css: -------------------------------------------------------------------------------- 1 | .next-steps { 2 | margin-top: 3rem; 3 | } 4 | 5 | .next-steps .vt-box { 6 | border: 1px solid var(--vt-c-bg-soft); 7 | } 8 | 9 | .next-steps .vt-box:hover { 10 | border-color: var(--vt-c-green-light); 11 | transition: border-color 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); 12 | } 13 | 14 | .vt-doc .next-steps-link { 15 | font-size: 20px; 16 | line-height: 1.4; 17 | letter-spacing: -0.02em; 18 | margin-bottom: 0.75em; 19 | display: block; 20 | color: var(--vt-c-green); 21 | } 22 | 23 | .vt-doc .next-steps-caption { 24 | margin-bottom: 0; 25 | color: var(--vt-c-text-2); 26 | transition: color 0.5s; 27 | } 28 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/pages.css: -------------------------------------------------------------------------------- 1 | /* always show anchors on /api/ and /style-guide/ pages */ 2 | .vt-doc.api h2 .header-anchor, 3 | .vt-doc.style-guide h2 .header-anchor { 4 | opacity: 1; 5 | } 6 | 7 | .vt-doc.sponsor h3 { 8 | text-align: center; 9 | padding-bottom: 1em; 10 | border-bottom: 1px solid var(--vt-c-divider-light); 11 | } 12 | 13 | .vt-doc.sponsor h3 .header-anchor { 14 | display: none; 15 | } 16 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/style-guide.css: -------------------------------------------------------------------------------- 1 | .style-example { 2 | border-radius: 8px 8px 12px 12px; 3 | margin: 1.6em 0; 4 | padding: 1.6em 1.6em 0.1px; 5 | position: relative; 6 | border: 1px solid transparent; 7 | transition: background-color 0.25s ease, border-color 0.25s ease; 8 | } 9 | 10 | .vt-doc .style-example h3 { 11 | margin: 0; 12 | font-size: 1.1em; 13 | } 14 | 15 | .style-example-bad { 16 | background: #f7e8e8; 17 | } 18 | .dark .style-example-bad { 19 | background: transparent; 20 | border-color: var(--vt-c-red); 21 | } 22 | 23 | .style-example-bad h3 { 24 | color: var(--vt-c-red); 25 | } 26 | 27 | .style-example-good { 28 | background: #ecfaf7; 29 | } 30 | .dark .style-example-good { 31 | background: transparent; 32 | border-color: var(--vt-c-green); 33 | } 34 | 35 | .style-example-good h3 { 36 | color: var(--vt-c-green); 37 | } 38 | 39 | .details summary { 40 | font-weight: bold !important; 41 | } 42 | 43 | .style-verb { 44 | font-size: 0.6em; 45 | display: inline-block; 46 | border-radius: 6px; 47 | font-size: 0.65em; 48 | line-height: 1; 49 | font-weight: 600; 50 | padding: 0.35em 0.4em 0.3em; 51 | position: relative; 52 | top: -0.15em; 53 | margin-right: 0.5em; 54 | color: var(--vt-c-bg); 55 | transition: color 0.5s; 56 | background-color: var(--vt-c-brand); 57 | } 58 | 59 | .style-verb.avoid { 60 | background-color: var(--vt-c-red); 61 | } 62 | .vt-doc summary { 63 | width: fit-content; 64 | cursor: pointer; 65 | } -------------------------------------------------------------------------------- /.vitepress/theme/styles/utilities.css: -------------------------------------------------------------------------------- 1 | .nowrap { 2 | white-space: nowrap; 3 | } 4 | 5 | .sr-only { 6 | position: absolute; 7 | width: 1px; 8 | height: 1px; 9 | padding: 0; 10 | margin: -1px; 11 | overflow: hidden; 12 | clip: rect(0, 0, 0, 0); 13 | border: 0; 14 | } 15 | -------------------------------------------------------------------------------- /.vitepress/theme/styles/vue-mastery.css: -------------------------------------------------------------------------------- 1 | .vue-mastery-link { 2 | background-color: var(--vt-c-bg-soft); 3 | border-radius: 8px; 4 | padding: 8px 16px 8px 8px; 5 | transition: color 0.5s, background-color 0.5s; 6 | } 7 | 8 | .vue-mastery-link a { 9 | display: flex; 10 | align-items: center; 11 | } 12 | 13 | .vue-mastery-link .banner { 14 | background-color: var(--vt-c-white-soft); 15 | border-radius: 4px; 16 | width: 96px; 17 | height: 56px; 18 | object-fit: cover; 19 | } 20 | 21 | .vue-mastery-link .description { 22 | flex: 1; 23 | font-weight: 500; 24 | font-size: 14px; 25 | line-height: 20px; 26 | color: var(--vt-c-text-1); 27 | margin: 0 0 0 16px; 28 | transition: color 0.5s; 29 | } 30 | 31 | .vue-mastery-link .description span { 32 | color: var(--vt-c-brand); 33 | } 34 | 35 | .vue-mastery-link .logo-wrapper { 36 | position: relative; 37 | width: 48px; 38 | height: 48px; 39 | border-radius: 50%; 40 | background-color: var(--vt-c-white); 41 | display: flex; 42 | justify-content: center; 43 | align-items: center; 44 | } 45 | 46 | .vue-mastery-link .logo-wrapper img { 47 | width: 25px; 48 | object-fit: contain; 49 | } 50 | 51 | @media (max-width: 576px) { 52 | .vue-mastery-link .banner { 53 | width: 56px; 54 | } 55 | 56 | .vue-mastery-link .description { 57 | font-size: 12px; 58 | line-height: 18px; 59 | } 60 | .vue-mastery-link .logo-wrapper { 61 | position: relative; 62 | width: 32px; 63 | height: 32px; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vuejs.org 2 | 3 | ## অবদান করুন 4 | 5 | Vue.JS বাংলা ডকুমেন্টেশন এ অবদান এর জন্য official vuejs-translations এর [discussions](https://github.com/vuejs-translations/guidelines/discussions/66) এ মন্তব্য করুন। 6 | 7 | এই সাইটটি [@vue/theme](https://github.com/vuejs/vue-theme) এর উপর নির্ভর করে [VitePress](https://github.com/vuejs/vitepress) দিয়ে তৈরি করা হয়েছে। । এই সাইটের বিষয় বা অবজেক্ট সমূহ Markdown ফরম্যাটে লেখা হয়েছে যা `src` এর মধ্যে পাবেন। সাধারণ পরিবর্তন, পরিবর্ধন, পরিমার্জন এর জন্য, আপনি সরাসরি GitHub-এ ফাইলটি সম্পাদন করতে পারবেন এবং মার্জ করার জন্য একটি Pull Request করতে পারেন। 8 | 9 | লোকাল ডেভেলপমেন্টের জন্য, প্যাকেজ ম্যানেজার হিসেবে [pnpm](https://pnpm.io/) ব্যবহার করা হয়েছে: 10 | 11 | ```bash 12 | pnpm i 13 | pnpm run dev 14 | ``` 15 | 16 | এই প্রকল্পের জন্য Node.js `v18` বা তার উচ্চতর সংস্করণ প্রয়োজন। এবং corepack সক্রিয় করার পরামর্শ দেওয়া হচ্ছে: 17 | 18 | ```bash 19 | corepack enable 20 | ``` 21 | 22 | ## বিষয়বস্তু নিয়ে কাজ করুন 23 | 24 | - সমর্থিত [মার্কডাউন এক্সটেনশন](https://vitepress.dev/guide/markdown) এবং [মার্কডাউনের মধ্যে Vue সিনট্যাক্স ব্যবহার](https://vitepress.dev/guide/using-vue) করার সুবিধা সম্পর্কে জানতে VitePress নথিপত্র দেখুন। 25 | 26 | - নথিপত্রের বিষয়বস্তু লেখা এবং রক্ষণাবেক্ষণের জন্য আমাদের নিয়মাবলী এবং পরামর্শগুলি জানতে [লেখার নির্দেশিকা](https://github.com/vuejs/docs/blob/main/.github/contributing/writing-guide.md) দেখুন। 27 | 28 | ## থিম নিয়ে কাজ করুন 29 | 30 | আপনি যদি থিমে পরিবর্তন করতে চান তবে [ডকুমেন্টেশন ও থিম সম্পাদনের নির্দেশাবলী দেখুন](https://github.com/vuejs/vue-theme#developing-with-real-content)। 31 | -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '@vue/theme/config' { 4 | import { UserConfig } from 'vitepress' 5 | const config: () => Promise 6 | export default config 7 | } 8 | 9 | declare module '@vue/theme/highlight' { 10 | const createHighlighter: () => Promise<(input: string) => string> 11 | export default createHighlighter 12 | } 13 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build.environment] 2 | NODE_VERSION = "22" 3 | 4 | [build] 5 | publish = ".vitepress/dist" 6 | command = "pnpm run build" 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "engines": { 3 | "node": ">=18.0.0" 4 | }, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vitepress", 8 | "build": "vitepress build", 9 | "preview": "vitepress preview", 10 | "preinstall": "npx only-allow pnpm", 11 | "type": "vue-tsc --noEmit" 12 | }, 13 | "dependencies": { 14 | "@vue/repl": "^4.4.2", 15 | "@vue/theme": "^2.3.0", 16 | "dynamics.js": "^1.1.5", 17 | "gsap": "^3.12.5", 18 | "vitepress": "^1.4.3", 19 | "vue": "^3.5.12" 20 | }, 21 | "devDependencies": { 22 | "@types/body-scroll-lock": "^3.1.2", 23 | "@types/markdown-it": "^14.1.2", 24 | "@types/node": "^22.7.5", 25 | "typescript": "^5.6.3", 26 | "vitepress-plugin-llms": "^0.0.8", 27 | "vue-tsc": "^2.1.6" 28 | }, 29 | "packageManager": "pnpm@9.12.1" 30 | } 31 | -------------------------------------------------------------------------------- /src/about/images/ben-hong.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/about/images/ben-hong.jpeg -------------------------------------------------------------------------------- /src/about/images/evan-you.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/about/images/evan-you.jpeg -------------------------------------------------------------------------------- /src/about/team.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | title: আমাদের দল দেখুন 4 | --- 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/about/team/Member.ts: -------------------------------------------------------------------------------- 1 | export interface Member { 2 | name: string 3 | avatarPic?: string 4 | title: string 5 | company?: string 6 | companyLink?: string 7 | projects: Link[] 8 | location: string | string[] 9 | languages: string[] 10 | website?: Link 11 | socials: Socials 12 | sponsor?: boolean | string 13 | reposPersonal?: string[] 14 | } 15 | 16 | export interface Link { 17 | label: string 18 | url: string 19 | } 20 | 21 | export interface Socials { 22 | github: string 23 | twitter?: string 24 | linkedin?: string 25 | codepen?: string 26 | } 27 | -------------------------------------------------------------------------------- /src/about/team/TeamHero.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 76 | -------------------------------------------------------------------------------- /src/api/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: API Reference 3 | sidebar: false 4 | page: true 5 | footer: false 6 | --- 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/developers/[developerSlug].md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | footer: false 4 | title: Vue Developer 5 | --- 6 | 7 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/developers/[developerSlug].paths.ts: -------------------------------------------------------------------------------- 1 | import developers from './developers.json' 2 | 3 | export default { 4 | paths: developers.map((developer) => { 5 | return { 6 | params: { 7 | developerId: developer.id, 8 | developerSlug: developer.slug, 9 | } 10 | } 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /src/developers/components/DeveloperCompensations.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 38 | -------------------------------------------------------------------------------- /src/developers/components/DeveloperEducation.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | 22 | 36 | -------------------------------------------------------------------------------- /src/developers/components/DeveloperHero.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 38 | 39 | 66 | -------------------------------------------------------------------------------- /src/developers/components/DeveloperImage.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 50 | 51 | 58 | -------------------------------------------------------------------------------- /src/developers/components/DeveloperJoin.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /src/developers/components/DeveloperProfileDiagram.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 31 | 32 | 45 | -------------------------------------------------------------------------------- /src/developers/components/type.ts: -------------------------------------------------------------------------------- 1 | export interface DeveloperExperienceDescription { 2 | isGrouped: boolean 3 | content: string | string[] 4 | } 5 | export interface DeveloperExperience { 6 | id: number 7 | role: string 8 | company: string 9 | startDate: string 10 | endDate: string 11 | period: string 12 | description: DeveloperExperienceDescription[] 13 | skills: string[] 14 | } 15 | 16 | export interface DeveloperEducation { 17 | id: number 18 | degree: string 19 | school: string 20 | startDate: string 21 | endDate: string 22 | } 23 | 24 | export interface DeveloperCompensations { 25 | partTime: string 26 | monthly: string 27 | } 28 | 29 | export interface DeveloperProfile { 30 | id: number 31 | slug: string 32 | name: string 33 | alias: string 34 | description: string[] 35 | proficiencies: string[] 36 | compensations: DeveloperCompensations 37 | location: string 38 | region: string 39 | experiences?: DeveloperExperience[] 40 | education?: DeveloperEducation[] 41 | } 42 | 43 | export interface DeveloperProfiles extends Array { 44 | } 45 | -------------------------------------------------------------------------------- /src/developers/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | footer: false 4 | title: Vue Developers 5 | --- 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/ecosystem/newsletters.md: -------------------------------------------------------------------------------- 1 | # কমিউনিটি নিউজলেটার {#community-newsletters} 2 | 3 | Vue.js কমিউনিটিতে বেশ কিছু চমৎকার ও তথ্যবহুল নিউজলেটার ও ব্লগ রয়েছে, যা আমাদের Vue.js ইকোসিস্টেমের সর্বশেষ আপডেট ও উন্নয়ন সম্পর্কে জানতে সহায়তা করে। নিচে কিছু সক্রিয় ও গুরুত্বপূর্ণ নিউজলেটার এবং ব্লগের তালিকা দেওয়া হলো: 4 | 5 | - [Vue.js Feed](https://vuejsfeed.com/) 6 | - [Michael Thiessen](https://michaelnthiessen.com/newsletter) 7 | - [Jakub Andrzejewski](https://dev.to/jacobandrewsky) 8 | - [Weekly Vue News](https://weekly-vue.news/) 9 | - [Vue.js Developers Newsletter](https://vuejsdevelopers.com/newsletter/) 10 | 11 | আপনি যদি কোনো মূল্যবান নিউজলেটার বা ব্লগ সম্পর্কে জানেন যা এখানে অন্তর্ভুক্ত করা হয়নি, তাহলে নিচের লিঙ্ক ব্যবহার করে একটি পুল রিকোয়েস্ট জমা দিন! 12 | -------------------------------------------------------------------------------- /src/ecosystem/themes.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | --- 4 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/ecosystem/themes/ThemeContact.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 50 | -------------------------------------------------------------------------------- /src/ecosystem/themes/ThemeHero.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 56 | -------------------------------------------------------------------------------- /src/ecosystem/themes/ThemeList.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 15 | 16 | 42 | -------------------------------------------------------------------------------- /src/ecosystem/themes/ThemePage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /src/error-reference/ErrorsTable.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | 29 | 35 | -------------------------------------------------------------------------------- /src/error-reference/errors.data.ts: -------------------------------------------------------------------------------- 1 | import { defineLoader } from 'vitepress' 2 | import { errorMessages } from 'vue/compiler-sfc' 3 | // @ts-expect-error internal api 4 | import { ErrorTypeStrings } from 'vue' 5 | 6 | function filterEmptyMsg(data: Record) { 7 | return Object.fromEntries(Object.entries(data).filter(([_, msg]) => msg)) 8 | } 9 | 10 | export default defineLoader({ 11 | load() { 12 | return { 13 | compiler: filterEmptyMsg(errorMessages), 14 | runtime: filterEmptyMsg(ErrorTypeStrings) 15 | } 16 | } 17 | }) 18 | -------------------------------------------------------------------------------- /src/error-reference/index.md: -------------------------------------------------------------------------------- 1 | 11 | 12 | # Production Error Code Reference {#error-reference} 13 | 14 | ## রানটাইম এরর {#runtime-errors} 15 | 16 | প্রোডাকশন বিল্ডে, নিম্নলিখিত এরর হ্যান্ডলার API-তে পাস করা হয়, আর্গুমেন্টটি সম্পূর্ণ তথ্যের স্ট্রিংয়ের পরিবর্তে একটি সংক্ষিপ্ত কোড হিসেবে প্রদর্শিত হবে: 17 | 18 | - [`app.config.errorHandler`](/api/application#app-config-errorhandler) 19 | - [`onErrorCaptured`](/api/composition-api-lifecycle#onerrorcaptured) (Composition API) 20 | - [`errorCaptured`](/api/options-lifecycle#errorcaptured) (Options API) 21 | 22 | নিম্নের সারণীতে প্রতিটি কোড তাদের সংশ্লিষ্ট সম্পূর্ণ তথ্যের স্ট্রিংয়ের সাথে ম্যাপ করা হয়েছে। 23 | 24 | 25 | 26 | ## কম্পাইলার এরর {#compiler-errors} 27 | 28 | নিচের সারণীতে উৎপন্ন কম্পাইলার এরর কোড এবং তাদের মূল বার্তার মধ্যে ম্যাপিং প্রদান করা হয়েছে। 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/examples/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | title: Examples 4 | aside: false 5 | footer: false 6 | outline: false 7 | --- 8 | 9 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/examples/src/attribute-bindings/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const message = ref('Hello World!') 6 | const isRed = ref(true) 7 | const color = ref('green') 8 | 9 | function toggleRed() { 10 | isRed.value = !isRed.value 11 | } 12 | 13 | function toggleColor() { 14 | color.value = color.value === 'green' ? 'blue' : 'green' 15 | } 16 | 17 | return { 18 | message, 19 | isRed, 20 | color, 21 | toggleRed, 22 | toggleColor 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/examples/src/attribute-bindings/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | message: 'Hello World!', 5 | isRed: true, 6 | color: 'green' 7 | } 8 | }, 9 | methods: { 10 | toggleRed() { 11 | this.isRed = !this.isRed 12 | }, 13 | toggleColor() { 14 | this.color = this.color === 'green' ? 'blue' : 'green' 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/examples/src/attribute-bindings/App/style.css: -------------------------------------------------------------------------------- 1 | .red { 2 | color: red; 3 | } -------------------------------------------------------------------------------- /src/examples/src/attribute-bindings/App/template.html: -------------------------------------------------------------------------------- 1 |

2 | 3 | আমাকে hover করে এই বাক্যের dynamic title দেখুন! 4 | 5 |

6 | 7 | 11 |

12 | এটি লাল হওয়া উচিত... তবে এটি toggle করতে আমাকে ক্লিক করুন৷ 13 |

14 | 15 | 16 |

17 | এটি সবুজ হওয়া উচিত এবং ক্লিক করলে সবুজ এবং নীলের মধ্যে টগল করা উচিত। 18 |

19 | -------------------------------------------------------------------------------- /src/examples/src/attribute-bindings/description.txt: -------------------------------------------------------------------------------- 1 | Here we are reactively binding element attributes / properties to the state. 2 | The :title syntax is short for v-bind:title. -------------------------------------------------------------------------------- /src/examples/src/cells/App/composition.js: -------------------------------------------------------------------------------- 1 | import Cell from './Cell.vue' 2 | import { cells } from './store.js' 3 | 4 | export default { 5 | components: { 6 | Cell 7 | }, 8 | setup() { 9 | const cols = cells.map((_, i) => String.fromCharCode(65 + i)) 10 | return { 11 | cols, 12 | cells 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/src/cells/App/options.js: -------------------------------------------------------------------------------- 1 | import Cell from './Cell.vue' 2 | import { cells } from './store.js' 3 | 4 | export default { 5 | components: { 6 | Cell 7 | }, 8 | data() { 9 | return { 10 | cols: cells.map((_, i) => String.fromCharCode(65 + i)), 11 | cells 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/src/cells/App/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } 4 | 5 | table { 6 | border-collapse: collapse; 7 | table-layout: fixed; 8 | width: 100%; 9 | } 10 | 11 | th { 12 | background-color: #eee; 13 | } 14 | 15 | tr:first-of-type th { 16 | width: 100px; 17 | } 18 | 19 | tr:first-of-type th:first-of-type { 20 | width: 25px; 21 | } 22 | 23 | td { 24 | border: 1px solid #ccc; 25 | height: 1.5em; 26 | overflow: hidden; 27 | } 28 | -------------------------------------------------------------------------------- /src/examples/src/cells/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 |
{{ c }}
{{ i - 1 }} 12 | 13 |
17 | -------------------------------------------------------------------------------- /src/examples/src/cells/Cell/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | import { cells, evalCell } from './store.js' 3 | 4 | export default { 5 | props: { 6 | c: Number, 7 | r: Number 8 | }, 9 | setup(props) { 10 | const editing = ref(false) 11 | 12 | function update(e) { 13 | editing.value = false 14 | cells[props.c][props.r] = e.target.value.trim() 15 | } 16 | 17 | return { 18 | cells, 19 | editing, 20 | evalCell, 21 | update 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/examples/src/cells/Cell/options.js: -------------------------------------------------------------------------------- 1 | import { cells, evalCell } from './store.js' 2 | 3 | export default { 4 | props: { 5 | c: Number, 6 | r: Number 7 | }, 8 | data() { 9 | return { 10 | editing: false, 11 | cells 12 | } 13 | }, 14 | methods: { 15 | evalCell, 16 | update(e) { 17 | this.editing = false 18 | cells[this.c][this.r] = e.target.value.trim() 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/examples/src/cells/Cell/style.css: -------------------------------------------------------------------------------- 1 | .cell, .cell input { 2 | height: 1.5em; 3 | line-height: 1.5; 4 | font-size: 15px; 5 | } 6 | 7 | .cell span { 8 | padding: 0 6px; 9 | } 10 | 11 | .cell input { 12 | width: 100%; 13 | box-sizing: border-box; 14 | } -------------------------------------------------------------------------------- /src/examples/src/cells/Cell/template.html: -------------------------------------------------------------------------------- 1 |
2 | 9 | {{ evalCell(cells[c][r]) }} 10 |
11 | -------------------------------------------------------------------------------- /src/examples/src/cells/description.txt: -------------------------------------------------------------------------------- 1 | https://eugenkiss.github.io/7guis/tasks/#cells -------------------------------------------------------------------------------- /src/examples/src/cells/store.js: -------------------------------------------------------------------------------- 1 | import { reactive } from 'vue' 2 | 3 | const COLS = 5 4 | const ROWS = 20 5 | 6 | export const cells = reactive( 7 | Array.from(Array(COLS).keys()).map((i) => 8 | Array.from(Array(ROWS).keys()).map((i) => '') 9 | ) 10 | ) 11 | 12 | // adapted from https://codesandbox.io/s/jotai-7guis-task7-cells-mzoit?file=/src/atoms.ts 13 | // by @dai-shi 14 | export function evalCell(exp) { 15 | if (!exp.startsWith('=')) { 16 | return exp 17 | } 18 | 19 | // = A1 + B2 ---> get(0,1) + get(1,2) 20 | exp = exp 21 | .slice(1) 22 | .replace( 23 | /\b([A-Z])(\d{1,2})\b/g, 24 | (_, c, r) => `get(${c.charCodeAt(0) - 65},${r})` 25 | ) 26 | 27 | try { 28 | return new Function('get', `return ${exp}`)(getCellValue) 29 | } catch (e) { 30 | return `#ERROR ${e}` 31 | } 32 | } 33 | 34 | function getCellValue(c, r) { 35 | const val = evalCell(cells[c][r]) 36 | const num = Number(val) 37 | return Number.isFinite(num) ? num : val 38 | } 39 | -------------------------------------------------------------------------------- /src/examples/src/circle-drawer/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, shallowReactive, toRaw } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const history = shallowReactive([[]]) 6 | const index = ref(0) 7 | const circles = ref([]) 8 | const selected = ref() 9 | const adjusting = ref(false) 10 | 11 | function onClick({ clientX: x, clientY: y }) { 12 | if (adjusting.value) { 13 | adjusting.value = false 14 | selected.value = null 15 | push() 16 | return 17 | } 18 | 19 | selected.value = [...circles.value].reverse().find(({ cx, cy, r }) => { 20 | const dx = cx - x 21 | const dy = cy - y 22 | return Math.sqrt(dx * dx + dy * dy) <= r 23 | }) 24 | 25 | if (!selected.value) { 26 | circles.value.push({ 27 | cx: x, 28 | cy: y, 29 | r: 50 30 | }) 31 | push() 32 | } 33 | } 34 | 35 | function adjust(circle) { 36 | selected.value = circle 37 | adjusting.value = true 38 | } 39 | 40 | function push() { 41 | history.length = ++index.value 42 | history.push(clone(circles.value)) 43 | console.log(toRaw(history)) 44 | } 45 | 46 | function undo() { 47 | circles.value = clone(history[--index.value]) 48 | } 49 | 50 | function redo() { 51 | circles.value = clone(history[++index.value]) 52 | } 53 | 54 | function clone(circles) { 55 | return circles.map((c) => ({ ...c })) 56 | } 57 | 58 | return { 59 | history, 60 | index, 61 | circles, 62 | selected, 63 | adjusting, 64 | onClick, 65 | adjust, 66 | undo, 67 | redo 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/examples/src/circle-drawer/App/options.js: -------------------------------------------------------------------------------- 1 | function clone(circles) { 2 | return circles.map((c) => ({ ...c })) 3 | } 4 | 5 | export default { 6 | data() { 7 | return { 8 | history: [[]], 9 | index: 0, 10 | circles: [], 11 | selected: null, 12 | adjusting: false 13 | } 14 | }, 15 | methods: { 16 | onClick({ clientX: x, clientY: y }) { 17 | if (this.adjusting) { 18 | this.adjusting = false 19 | this.selected = null 20 | this.push() 21 | return 22 | } 23 | 24 | this.selected = [...this.circles].reverse().find(({ cx, cy, r }) => { 25 | const dx = cx - x 26 | const dy = cy - y 27 | return Math.sqrt(dx * dx + dy * dy) <= r 28 | }) 29 | 30 | if (!this.selected) { 31 | this.circles.push({ 32 | cx: x, 33 | cy: y, 34 | r: 50 35 | }) 36 | this.push() 37 | } 38 | }, 39 | 40 | adjust(circle) { 41 | this.selected = circle 42 | this.adjusting = true 43 | }, 44 | 45 | push() { 46 | this.history.length = ++this.index 47 | this.history.push(clone(this.circles)) 48 | }, 49 | 50 | undo() { 51 | this.circles = clone(this.history[--this.index]) 52 | }, 53 | 54 | redo() { 55 | this.circles = clone(this.history[++this.index]) 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/examples/src/circle-drawer/App/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | overflow: hidden; 4 | } 5 | 6 | svg { 7 | width: 100vw; 8 | height: 100vh; 9 | background-color: #eee; 10 | } 11 | 12 | circle { 13 | stroke: #000; 14 | } 15 | 16 | .controls { 17 | position: fixed; 18 | top: 10px; 19 | left: 0; 20 | right: 0; 21 | text-align: center; 22 | } 23 | 24 | .controls button + button { 25 | margin-left: 6px; 26 | } 27 | 28 | .dialog { 29 | position: fixed; 30 | top: calc(50% - 50px); 31 | left: calc(50% - 175px); 32 | background: #fff; 33 | width: 350px; 34 | height: 100px; 35 | padding: 5px 20px; 36 | box-sizing: border-box; 37 | border-radius: 4px; 38 | text-align: center; 39 | box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.25); 40 | } 41 | 42 | .dialog input { 43 | display: block; 44 | width: 200px; 45 | margin: 0px auto; 46 | } 47 | 48 | .tip { 49 | text-align: center; 50 | padding: 0 50px; 51 | color: #bbb; 52 | } -------------------------------------------------------------------------------- /src/examples/src/circle-drawer/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | একটি বৃত্ত আঁকতে ক্যানভাসে ক্লিক করুন। এটি নির্বাচন করতে একটি বৃত্তে ক্লিক করুন। 5 | নির্বাচিত বৃত্তের ব্যাসার্ধ সামঞ্জস্য করতে ক্যানভাসে ডান-ক্লিক করুন। 6 |

7 |
8 | 17 |
18 | 19 |
20 | 21 | 22 |
23 | 24 |
25 |

Adjust radius of circle at ({{ selected.cx }}, {{ selected.cy }})

26 | 27 |
28 | -------------------------------------------------------------------------------- /src/examples/src/circle-drawer/description.txt: -------------------------------------------------------------------------------- 1 | https://eugenkiss.github.io/7guis/tasks/#circle -------------------------------------------------------------------------------- /src/examples/src/conditionals-and-loops/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const show = ref(true) 6 | const list = ref([1, 2, 3]) 7 | 8 | return { 9 | show, 10 | list 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/examples/src/conditionals-and-loops/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | show: true, 5 | list: [1, 2, 3] 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /src/examples/src/conditionals-and-loops/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 |
  • {{ item }}
  • 8 |
9 |

তালিকা খালি নয়, তবে লুকানো।

10 |

তালিকা খালি।

11 | -------------------------------------------------------------------------------- /src/examples/src/conditionals-and-loops/description.txt: -------------------------------------------------------------------------------- 1 | We can render content conditionally or in a loop with the v-if and v-for directives. -------------------------------------------------------------------------------- /src/examples/src/counter/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const count = ref(0) 6 | 7 | return { 8 | count 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/examples/src/counter/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | count: 0 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/examples/src/counter/App/template.html: -------------------------------------------------------------------------------- 1 | {{ count }} 2 | -------------------------------------------------------------------------------- /src/examples/src/counter/description.txt: -------------------------------------------------------------------------------- 1 | https://eugenkiss.github.io/7guis/tasks/#counter -------------------------------------------------------------------------------- /src/examples/src/crud/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, reactive, computed, watch } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const names = reactive(['Emil, Hans', 'Mustermann, Max', 'Tisch, Roman']) 6 | const selected = ref('') 7 | const prefix = ref('') 8 | const first = ref('') 9 | const last = ref('') 10 | 11 | const filteredNames = computed(() => 12 | names.filter((n) => 13 | n.toLowerCase().startsWith(prefix.value.toLowerCase()) 14 | ) 15 | ) 16 | 17 | watch(selected, (name) => { 18 | [last.value, first.value] = name.split(', ') 19 | }) 20 | 21 | function create() { 22 | if (hasValidInput()) { 23 | const fullName = `${last.value}, ${first.value}` 24 | if (!names.includes(fullName)) { 25 | names.push(fullName) 26 | first.value = last.value = '' 27 | } 28 | } 29 | } 30 | 31 | function update() { 32 | if (hasValidInput() && selected.value) { 33 | const i = names.indexOf(selected.value) 34 | names[i] = selected.value = `${last.value}, ${first.value}` 35 | } 36 | } 37 | 38 | function del() { 39 | if (selected.value) { 40 | const i = names.indexOf(selected.value) 41 | names.splice(i, 1) 42 | selected.value = first.value = last.value = '' 43 | } 44 | } 45 | 46 | function hasValidInput() { 47 | return first.value.trim() && last.value.trim() 48 | } 49 | 50 | return { 51 | filteredNames, 52 | selected, 53 | prefix, 54 | first, 55 | last, 56 | create, 57 | update, 58 | del 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/examples/src/crud/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | names: ['Emil, Hans', 'Mustermann, Max', 'Tisch, Roman'], 5 | selected: '', 6 | prefix: '', 7 | first: '', 8 | last: '' 9 | } 10 | }, 11 | computed: { 12 | filteredNames() { 13 | return this.names.filter((n) => 14 | n.toLowerCase().startsWith(this.prefix.toLowerCase()) 15 | ) 16 | } 17 | }, 18 | watch: { 19 | selected(name) { 20 | ;[this.last, this.first] = name.split(', ') 21 | } 22 | }, 23 | methods: { 24 | create() { 25 | if (this.hasValidInput()) { 26 | const fullName = `${this.last}, ${this.first}` 27 | if (!this.names.includes(fullName)) { 28 | this.names.push(fullName) 29 | this.first = this.last = '' 30 | } 31 | } 32 | }, 33 | update() { 34 | if (this.hasValidInput() && this.selected) { 35 | const i = this.names.indexOf(this.selected) 36 | this.names[i] = this.selected = `${this.last}, ${this.first}` 37 | } 38 | }, 39 | del() { 40 | if (this.selected) { 41 | const i = this.names.indexOf(this.selected) 42 | this.names.splice(i, 1) 43 | this.selected = this.first = this.last = '' 44 | } 45 | }, 46 | hasValidInput() { 47 | return this.first.trim() && this.last.trim() 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/examples/src/crud/App/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-size: inherit; 3 | } 4 | 5 | input { 6 | display: block; 7 | margin-bottom: 10px; 8 | } 9 | 10 | select { 11 | float: left; 12 | margin: 0 1em 1em 0; 13 | width: 14em; 14 | } 15 | 16 | .buttons { 17 | clear: both; 18 | } 19 | 20 | button + button { 21 | margin-left: 5px; 22 | } 23 | -------------------------------------------------------------------------------- /src/examples/src/crud/App/template.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /src/examples/src/crud/description.txt: -------------------------------------------------------------------------------- 1 | https://eugenkiss.github.io/7guis/tasks/#crud -------------------------------------------------------------------------------- /src/examples/src/fetching-data/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, watchEffect } from 'vue' 2 | 3 | const API_URL = `https://api.github.com/repos/vuejs/core/commits?per_page=3&sha=` 4 | const branches = ['main', 'minor'] 5 | 6 | export default { 7 | setup() { 8 | const currentBranch = ref(branches[0]) 9 | const commits = ref([]) 10 | 11 | watchEffect(async () => { 12 | // this effect will run immediately and then 13 | // re-run whenever currentBranch.value changes 14 | const url = `${API_URL}${currentBranch.value}` 15 | commits.value = await (await fetch(url)).json() 16 | }) 17 | 18 | function truncate(v) { 19 | const newline = v.indexOf('\n') 20 | return newline > 0 ? v.slice(0, newline) : v 21 | } 22 | 23 | function formatDate(v) { 24 | return v.replace(/T|Z/g, ' ') 25 | } 26 | 27 | return { 28 | branches, 29 | currentBranch, 30 | commits, 31 | truncate, 32 | formatDate 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/examples/src/fetching-data/App/options.js: -------------------------------------------------------------------------------- 1 | const API_URL = `https://api.github.com/repos/vuejs/core/commits?per_page=3&sha=` 2 | 3 | export default { 4 | data: () => ({ 5 | branches: ['main', 'minor'], 6 | currentBranch: 'main', 7 | commits: [] 8 | }), 9 | 10 | created() { 11 | // fetch on init 12 | this.fetchData() 13 | }, 14 | 15 | watch: { 16 | // re-fetch whenever currentBranch changes 17 | currentBranch: 'fetchData' 18 | }, 19 | 20 | methods: { 21 | async fetchData() { 22 | const url = `${API_URL}${this.currentBranch}` 23 | this.commits = await (await fetch(url)).json() 24 | }, 25 | truncate(v) { 26 | const newline = v.indexOf('\n') 27 | return newline > 0 ? v.slice(0, newline) : v 28 | }, 29 | formatDate(v) { 30 | return v.replace(/T|Z/g, ' ') 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/examples/src/fetching-data/App/style.css: -------------------------------------------------------------------------------- 1 | a { 2 | text-decoration: none; 3 | color: #42b883; 4 | } 5 | li { 6 | line-height: 1.5em; 7 | margin-bottom: 20px; 8 | } 9 | .author, 10 | .date { 11 | font-weight: bold; 12 | } 13 | -------------------------------------------------------------------------------- /src/examples/src/fetching-data/App/template.html: -------------------------------------------------------------------------------- 1 |

Latest Vue Core Commits

2 | 10 |

vuejs/core@{{ currentBranch }}

11 | 21 | -------------------------------------------------------------------------------- /src/examples/src/fetching-data/description.txt: -------------------------------------------------------------------------------- 1 | This example fetches latest Vue Core commits data from GitHub’s API and displays them as a list. 2 | You can switch between the two primary branches. 3 | -------------------------------------------------------------------------------- /src/examples/src/flight-booker/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const flightType = ref('one-way flight') 6 | const departureDate = ref(dateToString(new Date())) 7 | const returnDate = ref(departureDate.value) 8 | 9 | const isReturn = computed(() => flightType.value === 'return flight') 10 | 11 | const canBook = computed( 12 | () => 13 | !isReturn.value || 14 | stringToDate(returnDate.value) > stringToDate(departureDate.value) 15 | ) 16 | 17 | function book() { 18 | alert( 19 | isReturn.value 20 | ? `You have booked a return flight leaving on ${departureDate.value} and returning on ${returnDate.value}.` 21 | : `You have booked a one-way flight leaving on ${departureDate.value}.` 22 | ) 23 | } 24 | 25 | function stringToDate(str) { 26 | const [y, m, d] = str.split('-') 27 | return new Date(+y, m - 1, +d) 28 | } 29 | 30 | function dateToString(date) { 31 | return ( 32 | date.getFullYear() + 33 | '-' + 34 | pad(date.getMonth() + 1) + 35 | '-' + 36 | pad(date.getDate()) 37 | ) 38 | } 39 | 40 | function pad(n, s = String(n)) { 41 | return s.length < 2 ? `0${s}` : s 42 | } 43 | 44 | return { 45 | flightType, 46 | departureDate, 47 | returnDate, 48 | isReturn, 49 | canBook, 50 | book 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/examples/src/flight-booker/App/options.js: -------------------------------------------------------------------------------- 1 | function stringToDate(str) { 2 | const [y, m, d] = str.split('-') 3 | return new Date(+y, m - 1, +d) 4 | } 5 | 6 | function dateToString(date) { 7 | return ( 8 | date.getFullYear() + 9 | '-' + 10 | pad(date.getMonth() + 1) + 11 | '-' + 12 | pad(date.getDate()) 13 | ) 14 | } 15 | 16 | function pad(n, s = String(n)) { 17 | return s.length < 2 ? `0${s}` : s 18 | } 19 | 20 | export default { 21 | data() { 22 | return { 23 | flightType: 'one-way flight', 24 | departureDate: dateToString(new Date()), 25 | returnDate: dateToString(new Date()) 26 | } 27 | }, 28 | computed: { 29 | isReturn() { 30 | return this.flightType === 'return flight' 31 | }, 32 | canBook() { 33 | return ( 34 | !this.isReturn || 35 | stringToDate(this.returnDate) > stringToDate(this.departureDate) 36 | ) 37 | } 38 | }, 39 | methods: { 40 | book() { 41 | alert( 42 | this.isReturn 43 | ? `You have booked a return flight leaving on ${this.departureDate} and returning on ${this.returnDate}.` 44 | : `You have booked a one-way flight leaving on ${this.departureDate}.` 45 | ) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/examples/src/flight-booker/App/style.css: -------------------------------------------------------------------------------- 1 | select, 2 | input, 3 | button { 4 | display: block; 5 | margin: 0.5em 0; 6 | font-size: 15px; 7 | } 8 | 9 | input[disabled] { 10 | color: #999; 11 | } 12 | 13 | p { 14 | color: red; 15 | } -------------------------------------------------------------------------------- /src/examples/src/flight-booker/App/template.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

{{ canBook ? '' : 'Return date must be after departure date.' }}

12 | -------------------------------------------------------------------------------- /src/examples/src/flight-booker/description.txt: -------------------------------------------------------------------------------- 1 | https://eugenkiss.github.io/7guis/tasks/#flight -------------------------------------------------------------------------------- /src/examples/src/form-bindings/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const text = ref('Edit me') 6 | const checked = ref(true) 7 | const checkedNames = ref(['Jack']) 8 | const picked = ref('One') 9 | const selected = ref('A') 10 | const multiSelected = ref(['A']) 11 | 12 | return { 13 | text, 14 | checked, 15 | checkedNames, 16 | picked, 17 | selected, 18 | multiSelected 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/examples/src/form-bindings/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | text: 'Edit me', 5 | checked: true, 6 | checkedNames: ['Jack'], 7 | picked: 'One', 8 | selected: 'A', 9 | multiSelected: ['A'] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/examples/src/form-bindings/App/template.html: -------------------------------------------------------------------------------- 1 |

Text Input

2 | 3 |

{{ text }}

4 | 5 |

Checkbox

6 | 7 | 8 | 9 | 13 |

Multi Checkbox

14 | 15 | 16 | 17 | 18 | 19 | 20 |

Checked names: {{ checkedNames }}

21 | 22 |

Radio

23 | 24 | 25 |
26 | 27 | 28 |

Picked: {{ picked }}

29 | 30 |

Select

31 | 37 |

Selected: {{ selected }}

38 | 39 |

Multi Select

40 | 45 |

Selected: {{ multiSelected }}

46 | -------------------------------------------------------------------------------- /src/examples/src/form-bindings/description.txt: -------------------------------------------------------------------------------- 1 | We can create two-way bindings between state and form inputs using the v-model directive. -------------------------------------------------------------------------------- /src/examples/src/grid/App/composition.js: -------------------------------------------------------------------------------- 1 | import DemoGrid from './Grid.vue' 2 | import { ref } from 'vue' 3 | 4 | export default { 5 | components: { 6 | DemoGrid 7 | }, 8 | setup() { 9 | const searchQuery = ref('') 10 | const gridColumns = ['name', 'power'] 11 | const gridData = [ 12 | { name: 'Chuck Norris', power: Infinity }, 13 | { name: 'Bruce Lee', power: 9000 }, 14 | { name: 'Jackie Chan', power: 7000 }, 15 | { name: 'Jet Li', power: 8000 } 16 | ] 17 | 18 | return { 19 | searchQuery, 20 | gridColumns, 21 | gridData 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/examples/src/grid/App/options.js: -------------------------------------------------------------------------------- 1 | import DemoGrid from './Grid.vue' 2 | 3 | export default { 4 | components: { 5 | DemoGrid 6 | }, 7 | data: () => ({ 8 | searchQuery: '', 9 | gridColumns: ['name', 'power'], 10 | gridData: [ 11 | { name: 'Chuck Norris', power: Infinity }, 12 | { name: 'Bruce Lee', power: 9000 }, 13 | { name: 'Jackie Chan', power: 7000 }, 14 | { name: 'Jet Li', power: 8000 } 15 | ] 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /src/examples/src/grid/App/template.html: -------------------------------------------------------------------------------- 1 | 4 | 8 | -------------------------------------------------------------------------------- /src/examples/src/grid/Grid/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | 3 | export default { 4 | props: { 5 | data: Array, 6 | columns: Array, 7 | filterKey: String 8 | }, 9 | setup(props) { 10 | const sortKey = ref('') 11 | const sortOrders = ref( 12 | props.columns.reduce((o, key) => ((o[key] = 1), o), {}) 13 | ) 14 | 15 | const filteredData = computed(() => { 16 | let { data, filterKey } = props 17 | if (filterKey) { 18 | filterKey = filterKey.toLowerCase() 19 | data = data.filter((row) => { 20 | return Object.keys(row).some((key) => { 21 | return String(row[key]).toLowerCase().indexOf(filterKey) > -1 22 | }) 23 | }) 24 | } 25 | const key = sortKey.value 26 | if (key) { 27 | const order = sortOrders.value[key] 28 | data = data.slice().sort((a, b) => { 29 | a = a[key] 30 | b = b[key] 31 | return (a === b ? 0 : a > b ? 1 : -1) * order 32 | }) 33 | } 34 | return data 35 | }) 36 | 37 | function sortBy(key) { 38 | sortKey.value = key 39 | sortOrders.value[key] *= -1 40 | } 41 | 42 | function capitalize(str) { 43 | return str.charAt(0).toUpperCase() + str.slice(1) 44 | } 45 | 46 | return { 47 | sortKey, 48 | sortOrders, 49 | filteredData, 50 | sortBy, 51 | capitalize 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/examples/src/grid/Grid/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | data: Array, 4 | columns: Array, 5 | filterKey: String 6 | }, 7 | data() { 8 | return { 9 | sortKey: '', 10 | sortOrders: this.columns.reduce((o, key) => ((o[key] = 1), o), {}) 11 | } 12 | }, 13 | computed: { 14 | filteredData() { 15 | const sortKey = this.sortKey 16 | const filterKey = this.filterKey && this.filterKey.toLowerCase() 17 | const order = this.sortOrders[sortKey] || 1 18 | let data = this.data 19 | if (filterKey) { 20 | data = data.filter((row) => { 21 | return Object.keys(row).some((key) => { 22 | return String(row[key]).toLowerCase().indexOf(filterKey) > -1 23 | }) 24 | }) 25 | } 26 | if (sortKey) { 27 | data = data.slice().sort((a, b) => { 28 | a = a[sortKey] 29 | b = b[sortKey] 30 | return (a === b ? 0 : a > b ? 1 : -1) * order 31 | }) 32 | } 33 | return data 34 | } 35 | }, 36 | methods: { 37 | sortBy(key) { 38 | this.sortKey = key 39 | this.sortOrders[key] = this.sortOrders[key] * -1 40 | }, 41 | capitalize(str) { 42 | return str.charAt(0).toUpperCase() + str.slice(1) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/examples/src/grid/Grid/style.css: -------------------------------------------------------------------------------- 1 | table { 2 | border: 2px solid #42b983; 3 | border-radius: 3px; 4 | background-color: #fff; 5 | } 6 | 7 | th { 8 | background-color: #42b983; 9 | color: rgba(255, 255, 255, 0.66); 10 | cursor: pointer; 11 | user-select: none; 12 | } 13 | 14 | td { 15 | background-color: #f9f9f9; 16 | } 17 | 18 | th, 19 | td { 20 | min-width: 120px; 21 | padding: 10px 20px; 22 | } 23 | 24 | th.active { 25 | color: #fff; 26 | } 27 | 28 | th.active .arrow { 29 | opacity: 1; 30 | } 31 | 32 | .arrow { 33 | display: inline-block; 34 | vertical-align: middle; 35 | width: 0; 36 | height: 0; 37 | margin-left: 5px; 38 | opacity: 0.66; 39 | } 40 | 41 | .arrow.asc { 42 | border-left: 4px solid transparent; 43 | border-right: 4px solid transparent; 44 | border-bottom: 4px solid #fff; 45 | } 46 | 47 | .arrow.dsc { 48 | border-left: 4px solid transparent; 49 | border-right: 4px solid transparent; 50 | border-top: 4px solid #fff; 51 | } 52 | -------------------------------------------------------------------------------- /src/examples/src/grid/Grid/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 |
7 | {{ capitalize(key) }} 8 | 9 | 10 |
16 | {{entry[key]}} 17 |
21 |

No matches found.

-------------------------------------------------------------------------------- /src/examples/src/grid/description.txt: -------------------------------------------------------------------------------- 1 | An example of creating a reusable grid component and using it with external data. -------------------------------------------------------------------------------- /src/examples/src/handling-input/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const message = ref('Hello World!') 6 | 7 | function reverseMessage() { 8 | // Access/mutate the value of a ref via 9 | // its .value property. 10 | message.value = message.value.split('').reverse().join('') 11 | } 12 | 13 | function notify() { 14 | alert('navigation was prevented.') 15 | } 16 | 17 | return { 18 | message, 19 | reverseMessage, 20 | notify 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/examples/src/handling-input/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | message: 'Hello World!' 5 | } 6 | }, 7 | methods: { 8 | reverseMessage() { 9 | this.message = this.message.split('').reverse().join('') 10 | }, 11 | notify() { 12 | alert('navigation was prevented.') 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/src/handling-input/App/style.css: -------------------------------------------------------------------------------- 1 | button, a { 2 | display: block; 3 | margin-bottom: 1em; 4 | } -------------------------------------------------------------------------------- /src/examples/src/handling-input/App/template.html: -------------------------------------------------------------------------------- 1 | 5 |

{{ message }}

6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | A link with e.preventDefault() 22 | 23 | -------------------------------------------------------------------------------- /src/examples/src/handling-input/description.txt: -------------------------------------------------------------------------------- 1 | This example demonstrates handling user input with the v-on directive. -------------------------------------------------------------------------------- /src/examples/src/hello-world/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | // A "ref" is a reactive data source that stores a value. 6 | // Technically, we don't need to wrap the string with ref() 7 | // in order to display it, but we will see in the next 8 | // example why it is needed if we ever intend to change 9 | // the value. 10 | const message = ref('Hello World!') 11 | 12 | return { 13 | message 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/examples/src/hello-world/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | message: 'Hello World!' 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/examples/src/hello-world/App/template.html: -------------------------------------------------------------------------------- 1 |

{{ message }}

-------------------------------------------------------------------------------- /src/examples/src/hello-world/description.txt: -------------------------------------------------------------------------------- 1 | Say Hello World with Vue! -------------------------------------------------------------------------------- /src/examples/src/list-transition/App/composition.js: -------------------------------------------------------------------------------- 1 | import { shuffle as _shuffle } from 'lodash-es' 2 | import { ref } from 'vue' 3 | 4 | export default { 5 | setup() { 6 | const getInitialItems = () => [1, 2, 3, 4, 5] 7 | const items = ref(getInitialItems()) 8 | let id = items.value.length + 1 9 | 10 | function insert() { 11 | const i = Math.round(Math.random() * items.value.length) 12 | items.value.splice(i, 0, id++) 13 | } 14 | 15 | function reset() { 16 | items.value = getInitialItems() 17 | id = items.value.length + 1 18 | } 19 | 20 | function shuffle() { 21 | items.value = _shuffle(items.value) 22 | } 23 | 24 | function remove(item) { 25 | const i = items.value.indexOf(item) 26 | if (i > -1) { 27 | items.value.splice(i, 1) 28 | } 29 | } 30 | 31 | return { 32 | items, 33 | insert, 34 | reset, 35 | shuffle, 36 | remove 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/examples/src/list-transition/App/options.js: -------------------------------------------------------------------------------- 1 | import { shuffle } from 'lodash-es' 2 | 3 | const getInitialItems = () => [1, 2, 3, 4, 5] 4 | let id = getInitialItems().length + 1 5 | 6 | export default { 7 | data() { 8 | return { 9 | items: getInitialItems() 10 | } 11 | }, 12 | methods: { 13 | insert() { 14 | const i = Math.round(Math.random() * this.items.length) 15 | this.items.splice(i, 0, id++) 16 | }, 17 | reset() { 18 | this.items = getInitialItems() 19 | id = getInitialItems().length + 1 20 | }, 21 | shuffle() { 22 | this.items = shuffle(this.items) 23 | }, 24 | remove(item) { 25 | const i = this.items.indexOf(item) 26 | if (i > -1) { 27 | this.items.splice(i, 1) 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/examples/src/list-transition/App/style.css: -------------------------------------------------------------------------------- 1 | .container { 2 | position: relative; 3 | padding: 0; 4 | list-style-type: none; 5 | } 6 | 7 | .item { 8 | width: 100%; 9 | height: 30px; 10 | background-color: #f3f3f3; 11 | border: 1px solid #666; 12 | box-sizing: border-box; 13 | } 14 | 15 | /* 1. declare transition */ 16 | .fade-move, 17 | .fade-enter-active, 18 | .fade-leave-active { 19 | transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1); 20 | } 21 | 22 | /* 2. declare enter from and leave to state */ 23 | .fade-enter-from, 24 | .fade-leave-to { 25 | opacity: 0; 26 | transform: scaleY(0.01) translate(30px, 0); 27 | } 28 | 29 | /* 3. ensure leaving items are taken out of layout flow so that moving 30 | animations can be calculated correctly. */ 31 | .fade-leave-active { 32 | position: absolute; 33 | } 34 | -------------------------------------------------------------------------------- /src/examples/src/list-transition/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
  • 7 | {{ item }} 8 | 9 |
  • 10 |
    11 | -------------------------------------------------------------------------------- /src/examples/src/list-transition/description.txt: -------------------------------------------------------------------------------- 1 | FLIP list transitions with the built-in . 2 | https://aerotwist.com/blog/flip-your-animations/ -------------------------------------------------------------------------------- /src/examples/src/list-transition/import-map.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "lodash-es": "https://cdn.jsdelivr.net/npm/lodash-es/+esm" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/examples/src/markdown/App/composition.js: -------------------------------------------------------------------------------- 1 | import { marked } from 'marked' 2 | import { debounce } from 'lodash-es' 3 | import { ref, computed } from 'vue' 4 | 5 | export default { 6 | setup() { 7 | const input = ref('# hello') 8 | 9 | const output = computed(() => marked(input.value)) 10 | 11 | const update = debounce((e) => { 12 | input.value = e.target.value 13 | }, 100) 14 | 15 | return { 16 | input, 17 | output, 18 | update 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/examples/src/markdown/App/options.js: -------------------------------------------------------------------------------- 1 | import { marked } from 'marked' 2 | import { debounce } from 'lodash-es' 3 | 4 | export default { 5 | data: () => ({ 6 | input: '# hello' 7 | }), 8 | computed: { 9 | output() { 10 | return marked(this.input) 11 | } 12 | }, 13 | methods: { 14 | update: debounce(function (e) { 15 | this.input = e.target.value 16 | }, 100) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/examples/src/markdown/App/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } 4 | 5 | .editor { 6 | height: 100vh; 7 | display: flex; 8 | } 9 | 10 | .input, 11 | .output { 12 | overflow: auto; 13 | width: 50%; 14 | height: 100%; 15 | box-sizing: border-box; 16 | padding: 0 20px; 17 | } 18 | 19 | .input { 20 | border: none; 21 | border-right: 1px solid #ccc; 22 | resize: none; 23 | outline: none; 24 | background-color: #f6f6f6; 25 | font-size: 14px; 26 | font-family: 'Monaco', courier, monospace; 27 | padding: 20px; 28 | } 29 | 30 | code { 31 | color: #f66; 32 | } 33 | -------------------------------------------------------------------------------- /src/examples/src/markdown/App/template.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |
    5 | -------------------------------------------------------------------------------- /src/examples/src/markdown/description.txt: -------------------------------------------------------------------------------- 1 | A simple markdown editor. -------------------------------------------------------------------------------- /src/examples/src/markdown/import-map.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "marked": "https://cdn.jsdelivr.net/npm/marked/+esm", 4 | "lodash-es": "https://cdn.jsdelivr.net/npm/lodash-es/+esm" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/examples/src/modal/App/composition.js: -------------------------------------------------------------------------------- 1 | import Modal from './Modal.vue' 2 | import { ref } from 'vue' 3 | 4 | export default { 5 | components: { 6 | Modal 7 | }, 8 | setup() { 9 | const showModal = ref(false) 10 | 11 | return { 12 | showModal 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/examples/src/modal/App/options.js: -------------------------------------------------------------------------------- 1 | import Modal from './Modal.vue' 2 | 3 | export default { 4 | components: { 5 | Modal 6 | }, 7 | data() { 8 | return { 9 | showModal: false 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/examples/src/modal/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/examples/src/modal/Modal/composition.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | show: Boolean 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/examples/src/modal/Modal/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | show: Boolean 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/examples/src/modal/Modal/style.css: -------------------------------------------------------------------------------- 1 | .modal-mask { 2 | position: fixed; 3 | z-index: 9998; 4 | top: 0; 5 | left: 0; 6 | width: 100%; 7 | height: 100%; 8 | background-color: rgba(0, 0, 0, 0.5); 9 | display: flex; 10 | transition: opacity 0.3s ease; 11 | } 12 | 13 | .modal-container { 14 | width: 300px; 15 | margin: auto; 16 | padding: 20px 30px; 17 | background-color: #fff; 18 | border-radius: 2px; 19 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33); 20 | transition: all 0.3s ease; 21 | } 22 | 23 | .modal-header h3 { 24 | margin-top: 0; 25 | color: #42b983; 26 | } 27 | 28 | .modal-body { 29 | margin: 20px 0; 30 | } 31 | 32 | .modal-default-button { 33 | float: right; 34 | } 35 | 36 | /* 37 | * The following styles are auto-applied to elements with 38 | * transition="modal" when their visibility is toggled 39 | * by Vue.js. 40 | * 41 | * You can easily play with the modal transition by editing 42 | * these styles. 43 | */ 44 | 45 | .modal-enter-from { 46 | opacity: 0; 47 | } 48 | 49 | .modal-leave-to { 50 | opacity: 0; 51 | } 52 | 53 | .modal-enter-from .modal-container, 54 | .modal-leave-to .modal-container { 55 | -webkit-transform: scale(1.1); 56 | transform: scale(1.1); 57 | } 58 | -------------------------------------------------------------------------------- /src/examples/src/modal/Modal/template.html: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | -------------------------------------------------------------------------------- /src/examples/src/modal/description.txt: -------------------------------------------------------------------------------- 1 | Modal component with customizable slots and CSS transitions. -------------------------------------------------------------------------------- /src/examples/src/simple-component/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | import TodoItem from './TodoItem.vue' 3 | 4 | export default { 5 | components: { 6 | TodoItem 7 | }, 8 | setup() { 9 | const groceryList = ref([ 10 | { id: 0, text: 'Vegetables' }, 11 | { id: 1, text: 'Cheese' }, 12 | { id: 2, text: 'Whatever else humans are supposed to eat' } 13 | ]) 14 | 15 | return { 16 | groceryList 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/src/simple-component/App/options.js: -------------------------------------------------------------------------------- 1 | import TodoItem from './TodoItem.vue' 2 | 3 | export default { 4 | components: { 5 | TodoItem 6 | }, 7 | data() { 8 | return { 9 | groceryList: [ 10 | { id: 0, text: 'Vegetables' }, 11 | { id: 1, text: 'Cheese' }, 12 | { id: 2, text: 'Whatever else humans are supposed to eat' } 13 | ] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/examples/src/simple-component/App/template.html: -------------------------------------------------------------------------------- 1 |
      2 | 8 | 13 |
    14 | -------------------------------------------------------------------------------- /src/examples/src/simple-component/TodoItem/composition.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | todo: Object 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/examples/src/simple-component/TodoItem/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | todo: Object 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/examples/src/simple-component/TodoItem/template.html: -------------------------------------------------------------------------------- 1 |
  • {{ todo.text }}
  • -------------------------------------------------------------------------------- /src/examples/src/simple-component/description.txt: -------------------------------------------------------------------------------- 1 | Here we show the simplest possible component which accepts a prop and renders it. 2 | Learn more about components in the guide! -------------------------------------------------------------------------------- /src/examples/src/svg/App/composition.js: -------------------------------------------------------------------------------- 1 | import PolyGraph from './PolyGraph.vue' 2 | import { ref, reactive } from 'vue' 3 | 4 | export default { 5 | components: { 6 | PolyGraph 7 | }, 8 | setup() { 9 | const newLabel = ref('') 10 | const stats = reactive([ 11 | { label: 'A', value: 100 }, 12 | { label: 'B', value: 100 }, 13 | { label: 'C', value: 100 }, 14 | { label: 'D', value: 100 }, 15 | { label: 'E', value: 100 }, 16 | { label: 'F', value: 100 } 17 | ]) 18 | 19 | function add(e) { 20 | e.preventDefault() 21 | if (!newLabel.value) return 22 | stats.push({ 23 | label: newLabel.value, 24 | value: 100 25 | }) 26 | newLabel.value = '' 27 | } 28 | 29 | function remove(stat) { 30 | if (stats.length > 3) { 31 | stats.splice(stats.indexOf(stat), 1) 32 | } else { 33 | alert("Can't delete more!") 34 | } 35 | } 36 | 37 | return { 38 | newLabel, 39 | stats, 40 | add, 41 | remove 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/examples/src/svg/App/options.js: -------------------------------------------------------------------------------- 1 | import PolyGraph from './PolyGraph.vue' 2 | 3 | export default { 4 | components: { 5 | PolyGraph 6 | }, 7 | data: () => ({ 8 | newLabel: '', 9 | stats: [ 10 | { label: 'A', value: 100 }, 11 | { label: 'B', value: 100 }, 12 | { label: 'C', value: 100 }, 13 | { label: 'D', value: 100 }, 14 | { label: 'E', value: 100 }, 15 | { label: 'F', value: 100 } 16 | ] 17 | }), 18 | methods: { 19 | add(e) { 20 | e.preventDefault() 21 | if (!this.newLabel) return 22 | this.stats.push({ 23 | label: this.newLabel, 24 | value: 100 25 | }) 26 | this.newLabel = '' 27 | }, 28 | remove(stat) { 29 | if (this.stats.length > 3) { 30 | this.stats.splice(this.stats.indexOf(stat), 1) 31 | } else { 32 | alert("Can't delete more!") 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/examples/src/svg/App/style.css: -------------------------------------------------------------------------------- 1 | polygon { 2 | fill: #42b983; 3 | opacity: 0.75; 4 | } 5 | 6 | circle { 7 | fill: transparent; 8 | stroke: #999; 9 | } 10 | 11 | text { 12 | font-size: 10px; 13 | fill: #666; 14 | } 15 | 16 | label { 17 | display: inline-block; 18 | margin-left: 10px; 19 | width: 20px; 20 | } 21 | 22 | #raw { 23 | position: absolute; 24 | top: 0; 25 | left: 300px; 26 | } 27 | -------------------------------------------------------------------------------- /src/examples/src/svg/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 | 8 | 9 | {{stat.value}} 10 | 11 |
    12 | 13 |
    14 | 15 | 16 |
    17 | 18 |
    {{ stats }}
    19 | -------------------------------------------------------------------------------- /src/examples/src/svg/AxisLabel/composition.js: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue' 2 | import { valueToPoint } from './util.js' 3 | 4 | export default { 5 | props: { 6 | stat: Object, 7 | index: Number, 8 | total: Number 9 | }, 10 | setup(props) { 11 | const point = computed(() => 12 | valueToPoint(+props.stat.value + 10, props.index, props.total) 13 | ) 14 | 15 | return { 16 | point 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/examples/src/svg/AxisLabel/options.js: -------------------------------------------------------------------------------- 1 | import { valueToPoint } from './util.js' 2 | 3 | export default { 4 | props: { 5 | stat: Object, 6 | index: Number, 7 | total: Number 8 | }, 9 | computed: { 10 | point: function () { 11 | return valueToPoint(+this.stat.value + 10, this.index, this.total) 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/examples/src/svg/AxisLabel/template.html: -------------------------------------------------------------------------------- 1 | {{stat.label}} 2 | -------------------------------------------------------------------------------- /src/examples/src/svg/PolyGraph/composition.js: -------------------------------------------------------------------------------- 1 | import AxisLabel from './AxisLabel.vue' 2 | import { computed } from 'vue' 3 | import { valueToPoint } from './util.js' 4 | 5 | export default { 6 | components: { 7 | AxisLabel 8 | }, 9 | props: { 10 | stats: Array 11 | }, 12 | setup(props) { 13 | const points = computed(() => { 14 | const total = props.stats.length 15 | return props.stats 16 | .map((stat, i) => { 17 | const { x, y } = valueToPoint(stat.value, i, total) 18 | return `${x},${y}` 19 | }) 20 | .join(' ') 21 | }) 22 | 23 | return { 24 | points 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/examples/src/svg/PolyGraph/options.js: -------------------------------------------------------------------------------- 1 | import AxisLabel from './AxisLabel.vue' 2 | import { valueToPoint } from './util.js' 3 | 4 | export default { 5 | components: { 6 | AxisLabel 7 | }, 8 | props: { 9 | stats: Array 10 | }, 11 | computed: { 12 | // a computed property for the polygon's points 13 | points() { 14 | const total = this.stats.length 15 | return this.stats 16 | .map((stat, i) => { 17 | const { x, y } = valueToPoint(stat.value, i, total) 18 | return `${x},${y}` 19 | }) 20 | .join(' ') 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/examples/src/svg/PolyGraph/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/examples/src/svg/description.txt: -------------------------------------------------------------------------------- 1 | An SVG graph 2 | -------------------------------------------------------------------------------- /src/examples/src/svg/util.js: -------------------------------------------------------------------------------- 1 | export function valueToPoint(value, index, total) { 2 | const x = 0 3 | const y = -value * 0.8 4 | const angle = ((Math.PI * 2) / total) * index 5 | const cos = Math.cos(angle) 6 | const sin = Math.sin(angle) 7 | const tx = x * cos - y * sin + 100 8 | const ty = x * sin + y * cos + 100 9 | return { 10 | x: tx, 11 | y: ty 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/examples/src/temperature-converter/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const c = ref(0) 6 | const f = ref(32) 7 | 8 | function setC(e, v = +e.target.value) { 9 | c.value = v 10 | f.value = v * (9 / 5) + 32 11 | } 12 | 13 | function setF(e, v = +e.target.value) { 14 | f.value = v 15 | c.value = (v - 32) * (5 / 9) 16 | } 17 | 18 | return { 19 | c, 20 | f, 21 | setC, 22 | setF 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/examples/src/temperature-converter/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | c: 0, 5 | f: 32 6 | } 7 | }, 8 | methods: { 9 | setC(e, c = +e.target.value) { 10 | this.c = c 11 | this.f = c * (9 / 5) + 32 12 | }, 13 | setF(e, f = +e.target.value) { 14 | this.f = f 15 | this.c = (f - 32) * (5 / 9) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/examples/src/temperature-converter/App/template.html: -------------------------------------------------------------------------------- 1 | Celsius = 2 | Fahrenheit 3 | -------------------------------------------------------------------------------- /src/examples/src/temperature-converter/description.txt: -------------------------------------------------------------------------------- 1 | https://eugenkiss.github.io/7guis/tasks/#temp -------------------------------------------------------------------------------- /src/examples/src/timer/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, onUnmounted, computed } from 'vue' 2 | export default { 3 | setup() { 4 | const duration = ref(15 * 1000) 5 | const elapsed = ref(0) 6 | 7 | let lastTime 8 | let handle 9 | 10 | const update = () => { 11 | elapsed.value = performance.now() - lastTime 12 | if (elapsed.value >= duration.value) { 13 | cancelAnimationFrame(handle) 14 | } else { 15 | handle = requestAnimationFrame(update) 16 | } 17 | } 18 | 19 | const reset = () => { 20 | elapsed.value = 0 21 | lastTime = performance.now() 22 | update() 23 | } 24 | 25 | const progressRate = computed(() => 26 | Math.min(elapsed.value / duration.value, 1) 27 | ) 28 | 29 | reset() 30 | 31 | onUnmounted(() => { 32 | cancelAnimationFrame(handle) 33 | }) 34 | return { 35 | duration, 36 | elapsed, 37 | progressRate, 38 | reset 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/examples/src/timer/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | duration: 15 * 1000, 5 | elapsed: 0 6 | } 7 | }, 8 | created() { 9 | this.reset() 10 | }, 11 | unmounted() { 12 | cancelAnimationFrame(this.handle) 13 | }, 14 | computed: { 15 | progressRate() { 16 | return Math.min(this.elapsed / this.duration, 1) 17 | } 18 | }, 19 | methods: { 20 | update() { 21 | this.elapsed = performance.now() - this.lastTime 22 | if (this.elapsed >= this.duration) { 23 | cancelAnimationFrame(this.handle) 24 | } else { 25 | this.handle = requestAnimationFrame(this.update) 26 | } 27 | }, 28 | reset() { 29 | this.elapsed = 0 30 | this.lastTime = performance.now() 31 | this.update() 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/examples/src/timer/App/style.css: -------------------------------------------------------------------------------- 1 | .elapsed-container { 2 | width: 300px; 3 | } 4 | 5 | .elapsed-bar { 6 | background-color: red; 7 | height: 10px; 8 | } -------------------------------------------------------------------------------- /src/examples/src/timer/App/template.html: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    {{ (elapsed / 1000).toFixed(1) }}s
    6 | 7 |
    8 | Duration: 9 | {{ (duration / 1000).toFixed(1) }}s 10 |
    11 | 12 | -------------------------------------------------------------------------------- /src/examples/src/timer/description.txt: -------------------------------------------------------------------------------- 1 | https://eugenkiss.github.io/7guis/tasks/#timer -------------------------------------------------------------------------------- /src/examples/src/tree/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | import TreeItem from './TreeItem.vue' 3 | 4 | export default { 5 | components: { 6 | TreeItem 7 | }, 8 | setup() { 9 | const treeData = ref({ 10 | name: 'My Tree', 11 | children: [ 12 | { name: 'hello' }, 13 | { name: 'world' }, 14 | { 15 | name: 'child folder', 16 | children: [ 17 | { 18 | name: 'child folder', 19 | children: [{ name: 'hello' }, { name: 'world' }] 20 | }, 21 | { name: 'hello' }, 22 | { name: 'world' }, 23 | { 24 | name: 'child folder', 25 | children: [{ name: 'hello' }, { name: 'world' }] 26 | } 27 | ] 28 | } 29 | ] 30 | }) 31 | 32 | return { 33 | treeData 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/examples/src/tree/App/options.js: -------------------------------------------------------------------------------- 1 | import TreeItem from './TreeItem.vue' 2 | 3 | const treeData = { 4 | name: 'My Tree', 5 | children: [ 6 | { name: 'hello' }, 7 | { name: 'wat' }, 8 | { 9 | name: 'child folder', 10 | children: [ 11 | { 12 | name: 'child folder', 13 | children: [{ name: 'hello' }, { name: 'wat' }] 14 | }, 15 | { name: 'hello' }, 16 | { name: 'wat' }, 17 | { 18 | name: 'child folder', 19 | children: [{ name: 'hello' }, { name: 'wat' }] 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | 26 | export default { 27 | components: { 28 | TreeItem 29 | }, 30 | data() { 31 | return { 32 | treeData 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/examples/src/tree/App/style.css: -------------------------------------------------------------------------------- 1 | .item { 2 | cursor: pointer; 3 | line-height: 1.5; 4 | } 5 | .bold { 6 | font-weight: bold; 7 | } -------------------------------------------------------------------------------- /src/examples/src/tree/App/template.html: -------------------------------------------------------------------------------- 1 |
      2 | 3 |
    4 | -------------------------------------------------------------------------------- /src/examples/src/tree/TreeItem/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | 3 | export default { 4 | name: 'TreeItem', // necessary for self-reference 5 | props: { 6 | model: Object 7 | }, 8 | setup(props) { 9 | const isOpen = ref(false) 10 | const isFolder = computed(() => { 11 | return props.model.children && props.model.children.length 12 | }) 13 | 14 | function toggle() { 15 | isOpen.value = !isOpen.value 16 | } 17 | 18 | function changeType() { 19 | if (!isFolder.value) { 20 | props.model.children = [] 21 | addChild() 22 | isOpen.value = true 23 | } 24 | } 25 | 26 | function addChild() { 27 | props.model.children.push({ name: 'new stuff' }) 28 | } 29 | 30 | return { 31 | isOpen, 32 | isFolder, 33 | toggle, 34 | changeType, 35 | addChild 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/examples/src/tree/TreeItem/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'TreeItem', // necessary for self-reference 3 | props: { 4 | model: Object 5 | }, 6 | data() { 7 | return { 8 | isOpen: false 9 | } 10 | }, 11 | computed: { 12 | isFolder() { 13 | return this.model.children && this.model.children.length 14 | } 15 | }, 16 | methods: { 17 | toggle() { 18 | if (this.isFolder) { 19 | this.isOpen = !this.isOpen 20 | } 21 | }, 22 | changeType() { 23 | if (!this.isFolder) { 24 | this.model.children = [] 25 | this.addChild() 26 | this.isOpen = true 27 | } 28 | }, 29 | addChild() { 30 | this.model.children.push({ 31 | name: 'new stuff' 32 | }) 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/examples/src/tree/TreeItem/template.html: -------------------------------------------------------------------------------- 1 |
  • 2 |
    6 | {{ model.name }} 7 | [{{ isOpen ? '-' : '+' }}] 8 |
    9 |
      10 | 14 | 18 | 19 |
    • +
    • 20 |
    21 |
  • -------------------------------------------------------------------------------- /src/examples/src/tree/description.txt: -------------------------------------------------------------------------------- 1 | A nested tree component that recursively renders itself. 2 | You can double click on an item to turn it into a folder. -------------------------------------------------------------------------------- /src/guide/best-practices/images/AccessibilityChromeDeveloperTools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/best-practices/images/AccessibilityChromeDeveloperTools.png -------------------------------------------------------------------------------- /src/guide/best-practices/images/AccessibleARIAdescribedby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/best-practices/images/AccessibleARIAdescribedby.png -------------------------------------------------------------------------------- /src/guide/best-practices/images/AccessibleARIAlabelDevTools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/best-practices/images/AccessibleARIAlabelDevTools.png -------------------------------------------------------------------------------- /src/guide/best-practices/images/AccessibleARIAlabelledbyDevTools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/best-practices/images/AccessibleARIAlabelledbyDevTools.png -------------------------------------------------------------------------------- /src/guide/best-practices/images/AccessibleLabelChromeDevTools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/best-practices/images/AccessibleLabelChromeDevTools.png -------------------------------------------------------------------------------- /src/guide/best-practices/images/AccessiblePlaceholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/best-practices/images/AccessiblePlaceholder.png -------------------------------------------------------------------------------- /src/guide/built-ins/images/transition-classes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/built-ins/images/transition-classes.png -------------------------------------------------------------------------------- /src/guide/built-ins/keep-alive-demos/CompA.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /src/guide/built-ins/keep-alive-demos/CompB.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /src/guide/built-ins/keep-alive-demos/SwitchComponent.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 25 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/Basic.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | 15 | 26 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/BetweenComponents.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 23 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/BetweenElements.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | 28 | 63 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/CssAnimation.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 16 | 17 | 36 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/JsHooks.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 56 | 57 | 66 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/ListBasic.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 31 | 32 | 43 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/ListMove.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 45 | 46 | 65 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/ListStagger.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 63 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/NestedTransitions.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 16 | 17 | 66 | -------------------------------------------------------------------------------- /src/guide/built-ins/transition-demos/SlideFade.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | 15 | 30 | -------------------------------------------------------------------------------- /src/guide/components/images/named-slots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/components/images/named-slots.png -------------------------------------------------------------------------------- /src/guide/components/images/prop-drilling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/components/images/prop-drilling.png -------------------------------------------------------------------------------- /src/guide/components/images/provide-inject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/components/images/provide-inject.png -------------------------------------------------------------------------------- /src/guide/components/images/slots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/components/images/slots.png -------------------------------------------------------------------------------- /src/guide/essentials/images/components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/essentials/images/components.png -------------------------------------------------------------------------------- /src/guide/essentials/images/directive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/essentials/images/directive.png -------------------------------------------------------------------------------- /src/guide/essentials/images/lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/essentials/images/lifecycle.png -------------------------------------------------------------------------------- /src/guide/extras/demos/AnimateWatcher.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 24 | 25 | 31 | -------------------------------------------------------------------------------- /src/guide/extras/demos/Colors.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | 22 | 29 | -------------------------------------------------------------------------------- /src/guide/extras/demos/DisabledButton.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | 25 | 54 | -------------------------------------------------------------------------------- /src/guide/extras/demos/SpreadSheet.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 26 | 27 | 47 | -------------------------------------------------------------------------------- /src/guide/extras/demos/SpreadSheetCell.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 30 | 31 | 54 | -------------------------------------------------------------------------------- /src/guide/extras/demos/spreadSheetStore.js: -------------------------------------------------------------------------------- 1 | import { reactive } from 'vue' 2 | 3 | const COLS = 3 4 | const ROWS = 3 5 | 6 | export const cells = reactive( 7 | Array.from(Array(COLS).keys()).map((i) => 8 | Array.from(Array(ROWS).keys()).map((i) => '') 9 | ) 10 | ) 11 | 12 | // initial state for demo 13 | cells[0][0] = '1' 14 | cells[0][1] = '2' 15 | cells[0][2] = '= A0 + A1' 16 | 17 | // adapted from https://codesandbox.io/s/jotai-7guis-task7-cells-mzoit?file=/src/atoms.ts 18 | // by @dai-shi 19 | export function evalCell(exp) { 20 | if (!exp.startsWith('=')) { 21 | return exp 22 | } 23 | 24 | // = A1 + B2 ---> get(0,1) + get(1,2) 25 | exp = exp 26 | .slice(1) 27 | .replace( 28 | /\b([A-Z])(\d{1,2})\b/g, 29 | (_, c, r) => `get(${c.charCodeAt(0) - 65},${r})` 30 | ) 31 | 32 | try { 33 | return new Function('get', `return ${exp}`)(getCellValue) 34 | } catch (e) { 35 | return `#ERROR ${e}` 36 | } 37 | } 38 | 39 | function getCellValue(c, r) { 40 | const val = evalCell(cells[c][r]) 41 | const num = Number(val) 42 | return Number.isFinite(num) ? num : val 43 | } 44 | -------------------------------------------------------------------------------- /src/guide/extras/images/composition-api-after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/extras/images/composition-api-after.png -------------------------------------------------------------------------------- /src/guide/extras/images/options-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/extras/images/options-api.png -------------------------------------------------------------------------------- /src/guide/extras/images/render-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/extras/images/render-pipeline.png -------------------------------------------------------------------------------- /src/guide/reusability/mouse.js: -------------------------------------------------------------------------------- 1 | import { ref, onMounted, onUnmounted } from 'vue' 2 | 3 | export function useMouse() { 4 | const x = ref(0) 5 | const y = ref(0) 6 | 7 | function update(event) { 8 | x.value = event.pageX 9 | y.value = event.pageY 10 | } 11 | 12 | onMounted(() => window.addEventListener('mousemove', update)) 13 | onUnmounted(() => window.removeEventListener('mousemove', update)) 14 | 15 | return { x, y } 16 | } 17 | -------------------------------------------------------------------------------- /src/guide/scaling-up/images/devtools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/scaling-up/images/devtools.png -------------------------------------------------------------------------------- /src/guide/scaling-up/images/state-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/guide/scaling-up/images/state-flow.png -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | title: Vue.js - প্রগতিশীল জাভাস্ক্রিপ্ট ফ্রেমওয়ার্ক 4 | --- 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/partners/[partnerId].md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | footer: false 4 | --- 5 | 6 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/partners/[partnerId].paths.ts: -------------------------------------------------------------------------------- 1 | import partners from './partners.json' 2 | import { normalizeName } from './components/utils' 3 | 4 | export default { 5 | paths: partners.map((p) => { 6 | return { 7 | params: { 8 | partnerId: normalizeName(p.name) 9 | } 10 | } 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /src/partners/all.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | footer: false 4 | --- 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/partners/components/PartnerAll.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 35 | 36 | 60 | -------------------------------------------------------------------------------- /src/partners/components/PartnerHero.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | -------------------------------------------------------------------------------- /src/partners/components/PartnerJoin.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | -------------------------------------------------------------------------------- /src/partners/components/PartnerLanding.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 43 | -------------------------------------------------------------------------------- /src/partners/components/PartnerList.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 25 | -------------------------------------------------------------------------------- /src/partners/components/PartnerLocation.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /src/partners/components/type.ts: -------------------------------------------------------------------------------- 1 | export interface Partner { 2 | name: string 3 | logo: string 4 | hero?: string 5 | flipLogo?: boolean 6 | intro: string 7 | description: string[] 8 | proficiencies: string[] 9 | region: string[] 10 | location: string[] 11 | website: { 12 | text: string 13 | url: string 14 | } 15 | contact?: string 16 | contactPage?: string; 17 | hiring?: string 18 | platinum?: boolean 19 | } 20 | -------------------------------------------------------------------------------- /src/partners/components/utils.ts: -------------------------------------------------------------------------------- 1 | export function track() { 2 | fathom.trackGoal('TTDUIE6G', 0) 3 | } 4 | 5 | export function normalizeName(name: string) { 6 | return name.toLowerCase().replace(/\s+/g, '') 7 | } 8 | 9 | export function getHero(img: string | undefined, name: string) { 10 | return `/images/partners/${img || `${normalizeName(name)}-hero.jpg`}` 11 | } 12 | 13 | export function getLogo(img: string, flip = false) { 14 | if (flip) img = img.replace(/(\.\w+$)/, '-dark$1') 15 | return `/images/partners/${img}` 16 | } 17 | -------------------------------------------------------------------------------- /src/partners/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | footer: false 4 | title: Vue Partners 5 | --- 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/public/_headers: -------------------------------------------------------------------------------- 1 | /* 2 | X-Frame-Options: ALLOW-FROM https://staging.certification.vuejs.org https://certification.vuejs.org https://certificates.dev https://staging.certificates.dev https://alemira.com https://*.alemira.com 3 | Content-Security-Policy: frame-ancestors https://staging.certification.vuejs.org https://certification.vuejs.org https://certificates.dev https://staging.certificates.dev https://alemira.com https://*.alemira.com 4 | 5 | /assets/* 6 | cache-control: max-age=31536000 7 | cache-control: immutable 8 | -------------------------------------------------------------------------------- /src/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/logo.png -------------------------------------------------------------------------------- /src/public/images/partners/64robots-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/64robots-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/curotec-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/curotec-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/curotec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/curotec.png -------------------------------------------------------------------------------- /src/public/images/partners/epicmax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/epicmax.png -------------------------------------------------------------------------------- /src/public/images/partners/herodevs-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/herodevs-dark.png -------------------------------------------------------------------------------- /src/public/images/partners/herodevs-hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/herodevs-hero.png -------------------------------------------------------------------------------- /src/public/images/partners/herodevs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/herodevs.png -------------------------------------------------------------------------------- /src/public/images/partners/jump24-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/public/images/partners/jump24-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/jump24-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/jump24.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/public/images/partners/monterail-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/monterail-dark.png -------------------------------------------------------------------------------- /src/public/images/partners/monterail-hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/monterail-hero.png -------------------------------------------------------------------------------- /src/public/images/partners/monterail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/monterail.png -------------------------------------------------------------------------------- /src/public/images/partners/passionatepeople-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/passionatepeople-dark.png -------------------------------------------------------------------------------- /src/public/images/partners/passionatepeople-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/passionatepeople-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/passionatepeople.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/passionatepeople.png -------------------------------------------------------------------------------- /src/public/images/partners/proxify-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/proxify-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/redberry-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/redberry-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/redberry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/redberry.png -------------------------------------------------------------------------------- /src/public/images/partners/tighten-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/tighten-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/vehikl-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/vehikl-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/webreinvent-hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/webreinvent-hero.jpg -------------------------------------------------------------------------------- /src/public/images/partners/webreinvent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/partners/webreinvent.png -------------------------------------------------------------------------------- /src/public/images/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/images/paypal.png -------------------------------------------------------------------------------- /src/public/logo-uwu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-translations/docs-bn/743baa57e92e07111893291a3f3ea77d4907dce7/src/public/logo-uwu.png -------------------------------------------------------------------------------- /src/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/public/service-worker.js: -------------------------------------------------------------------------------- 1 | // force clearing previous service worker 2 | self.addEventListener('install', function (e) { 3 | self.skipWaiting() 4 | }) 5 | 6 | self.addEventListener('activate', function (e) { 7 | self.registration 8 | .unregister() 9 | .then(function () { 10 | return self.clients.matchAll() 11 | }) 12 | .then(function (clients) { 13 | clients.forEach((client) => client.navigate(client.url)) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /src/tutorial/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | page: true 3 | title: Tutorial 4 | sidebar: false 5 | aside: false 6 | footer: false 7 | returnToTop: false 8 | --- 9 | 10 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/tutorial/src/step-1/App/template.html: -------------------------------------------------------------------------------- 1 |

    Hello World!

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-10/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const todoId = ref(1) 6 | const todoData = ref(null) 7 | 8 | async function fetchData() { 9 | todoData.value = null 10 | const res = await fetch( 11 | `https://jsonplaceholder.typicode.com/todos/${todoId.value}` 12 | ) 13 | todoData.value = await res.json() 14 | } 15 | 16 | fetchData() 17 | 18 | return { 19 | todoId, 20 | todoData 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/tutorial/src/step-10/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | todoId: 1, 5 | todoData: null 6 | } 7 | }, 8 | methods: { 9 | async fetchData() { 10 | this.todoData = null 11 | const res = await fetch( 12 | `https://jsonplaceholder.typicode.com/todos/${this.todoId}` 13 | ) 14 | this.todoData = await res.json() 15 | } 16 | }, 17 | mounted() { 18 | this.fetchData() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/tutorial/src/step-10/App/template.html: -------------------------------------------------------------------------------- 1 |

    Todo id: {{ todoId }}

    2 | 3 |

    Loading...

    4 |
    {{ todoData }}
    5 | -------------------------------------------------------------------------------- /src/tutorial/src/step-10/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, watch } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const todoId = ref(1) 6 | const todoData = ref(null) 7 | 8 | async function fetchData() { 9 | todoData.value = null 10 | const res = await fetch( 11 | `https://jsonplaceholder.typicode.com/todos/${todoId.value}` 12 | ) 13 | todoData.value = await res.json() 14 | } 15 | 16 | fetchData() 17 | 18 | watch(todoId, fetchData) 19 | 20 | return { 21 | todoId, 22 | todoData 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/tutorial/src/step-10/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | todoId: 1, 5 | todoData: null 6 | } 7 | }, 8 | methods: { 9 | async fetchData() { 10 | this.todoData = null 11 | const res = await fetch( 12 | `https://jsonplaceholder.typicode.com/todos/${this.todoId}` 13 | ) 14 | this.todoData = await res.json() 15 | } 16 | }, 17 | mounted() { 18 | this.fetchData() 19 | }, 20 | watch: { 21 | todoId() { 22 | this.fetchData() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/tutorial/src/step-10/description.md: -------------------------------------------------------------------------------- 1 | # Watchers {#watchers} 2 | 3 | কখনও কখনও আমাদের প্রতিক্রিয়াশীলভাবে "পার্শ্ব প্রতিক্রিয়া" সম্পাদন করতে হতে পারে - উদাহরণস্বরূপ, কনসোলে একটি নম্বর লগ করা যখন এটি পরিবর্তন হয়। আমরা পর্যবেক্ষকদের সাথে এটি অর্জন করতে পারি: 4 | 5 |
    6 | 7 | ```js 8 | import { ref, watch } from 'vue' 9 | 10 | const count = ref(0) 11 | 12 | watch(count, (newCount) => { 13 | // yes, console.log() is a side effect 14 | console.log(`new count is: ${newCount}`) 15 | }) 16 | ``` 17 | 18 | `watch()` সরাসরি একটি রেফ দেখতে পারে এবং যখনই `count` এর মান পরিবর্তন হয় তখন কলব্যাকটি বরখাস্ত হয়ে যায়। `watch()` অন্যান্য ধরনের ডেটা উত্সও দেখতে পারে - আরও বিশদ বিবরণ গাইড - ওয়াচার্স-এ দেওয়া আছে। 19 | 20 |
    21 |
    22 | 23 | ```js 24 | export default { 25 | data() { 26 | return { 27 | count: 0 28 | } 29 | }, 30 | watch: { 31 | count(newCount) { 32 | // yes, console.log() is a side effect 33 | console.log(`new count is: ${newCount}`) 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | এখানে, আমরা `count` বৈশিষ্ট্যের পরিবর্তনগুলি দেখতে `watch` বিকল্পটি ব্যবহার করছি। ওয়াচ কলব্যাক বলা হয় যখন `count` পরিবর্তিত হয়, এবং আর্গুমেন্ট হিসাবে নতুন মান গ্রহণ করে। আরো বিশদ বিবরণ গাইড - ওয়াচার্স-এ দেওয়া আছে। 40 | 41 |
    42 | 43 | কনসোলে লগ করার চেয়ে একটি আরও বাস্তব উদাহরণ হল একটি আইডি পরিবর্তন হলে নতুন ডেটা আনা। আমাদের কাছে কোডটি কম্পোনেন্ট মাউন্টে একটি মক API থেকে todos ডেটা আনছে। এছাড়াও একটি বোতাম রয়েছে যা টোডো আইডি বৃদ্ধি করে যা আনতে হবে। বোতামটি ক্লিক করার সময় একটি নতুন করণীয় নিয়ে আসে এমন একটি প্রহরী প্রয়োগ করার চেষ্টা করুন৷ 44 | -------------------------------------------------------------------------------- /src/tutorial/src/step-11/App/composition.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // register child component 3 | } 4 | -------------------------------------------------------------------------------- /src/tutorial/src/step-11/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // register child component 3 | } 4 | -------------------------------------------------------------------------------- /src/tutorial/src/step-11/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-11/ChildComp/template.html: -------------------------------------------------------------------------------- 1 |

    A Child Component!

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-11/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import ChildComp from './ChildComp.vue' 2 | 3 | export default { 4 | components: { 5 | ChildComp 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/tutorial/src/step-11/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | import ChildComp from './ChildComp.vue' 2 | 3 | export default { 4 | components: { 5 | ChildComp 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/tutorial/src/step-11/_hint/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | import ChildComp from './ChildComp.vue' 3 | 4 | export default { 5 | components: { 6 | ChildComp 7 | }, 8 | setup() { 9 | const greeting = ref('Hello from parent') 10 | 11 | return { 12 | greeting 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/App/options.js: -------------------------------------------------------------------------------- 1 | import ChildComp from './ChildComp.vue' 2 | 3 | export default { 4 | components: { 5 | ChildComp 6 | }, 7 | data() { 8 | return { 9 | greeting: 'Hello from parent' 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/ChildComp/composition.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | msg: String 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/ChildComp/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | msg: String 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/ChildComp/template.html: -------------------------------------------------------------------------------- 1 |

    {{ msg || 'No props passed yet' }}

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/_hint/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-12/description.md: -------------------------------------------------------------------------------- 1 | # Props {#props} 2 | 3 | একটি চাইল্ড কম্পোনেন্ট **props** এর মাধ্যমে পিতামাতার কাছ থেকে ইনপুট গ্রহণ করতে পারে। প্রথমত, এটি যে প্রপগুলি গ্রহণ করে তা ঘোষণা করতে হবে: 4 | 5 |
    6 |
    7 | 8 | ```vue 9 | 10 | 15 | ``` 16 | 17 | দ্রষ্টব্য `defineProps()` একটি কম্পাইল-টাইম ম্যাক্রো এবং এটি আমদানি করার প্রয়োজন নেই। একবার ঘোষণা করা হলে, চাইল্ড কম্পোনেন্টের টেমপ্লেটে `msg` প্রপ ব্যবহার করা যেতে পারে। এটি `defineProps()` এর প্রত্যাবর্তিত অবজেক্টর মাধ্যমে জাভাস্ক্রিপ্টে অ্যাক্সেস করা যেতে পারে। 18 | 19 |
    20 | 21 |
    22 | 23 | ```js 24 | // in child component 25 | export default { 26 | props: { 27 | msg: String 28 | }, 29 | setup(props) { 30 | // access props.msg 31 | } 32 | } 33 | ``` 34 | 35 | একবার ঘোষণা করা হলে, `this`-এ `msg` প্রপ প্রকাশ করা হয় এবং চাইল্ড কম্পোনেন্টের টেমপ্লেটে ব্যবহার করা যেতে পারে। প্রাপ্ত প্রপগুলিকে প্রথম আর্গুমেন্ট হিসাবে `setup()`-এ পাঠানো হয়। 36 | 37 |
    38 | 39 |
    40 | 41 |
    42 | 43 | ```js 44 | // in child component 45 | export default { 46 | props: { 47 | msg: String 48 | } 49 | } 50 | ``` 51 | 52 | একবার ঘোষণা করা হলে, `this`-এ `msg` প্রপ প্রকাশ করা হয় এবং চাইল্ড কম্পোনেন্টের টেমপ্লেটে ব্যবহার করা যেতে পারে। 53 | 54 |
    55 | 56 | অভিভাবক গুণাবলীর মতই সন্তানকে প্রপ দিতে পারেন। একটি গতিশীল মান পাস করতে, আমরা `v-bind` বাক্য গঠনও ব্যবহার করতে পারি: 57 | 58 |
    59 | 60 | ```vue-html 61 | 62 | ``` 63 | 64 |
    65 |
    66 | 67 | ```vue-html 68 | 69 | ``` 70 | 71 |
    72 | 73 | এখন এডিটরে নিজেই চেষ্টা করে দেখুন। 74 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | import ChildComp from './ChildComp.vue' 3 | 4 | export default { 5 | components: { 6 | ChildComp 7 | }, 8 | setup() { 9 | const childMsg = ref('No child msg yet') 10 | 11 | return { 12 | childMsg 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/App/options.js: -------------------------------------------------------------------------------- 1 | import ChildComp from './ChildComp.vue' 2 | 3 | export default { 4 | components: { 5 | ChildComp 6 | }, 7 | data() { 8 | return { 9 | childMsg: 'No child msg yet' 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/App/template.html: -------------------------------------------------------------------------------- 1 | 2 |

    {{ childMsg }}

    3 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/ChildComp/composition.js: -------------------------------------------------------------------------------- 1 | export default { 2 | emits: ['response'], 3 | setup(props, { emit }) { 4 | emit('response', 'hello from child') 5 | return {} 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/ChildComp/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | emits: ['response'], 3 | created() { 4 | this.$emit('response', 'hello from child') 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/ChildComp/template.html: -------------------------------------------------------------------------------- 1 |

    Child component

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/_hint/App/template.html: -------------------------------------------------------------------------------- 1 | 2 |

    {{ childMsg }}

    3 | -------------------------------------------------------------------------------- /src/tutorial/src/step-13/description.md: -------------------------------------------------------------------------------- 1 | # Emits {#emits} 2 | 3 | props প্রাপ্তির পাশাপাশি, একটি 'child component' 'parent component' এর কাছে ইভেন্টগুলি emit করতে পারে: 4 | 5 |
    6 |
    7 | 8 | ```vue 9 | 16 | ``` 17 | 18 |
    19 | 20 |
    21 | 22 | ```js 23 | export default { 24 | // declare emitted events 25 | emits: ['response'], 26 | setup(props, { emit }) { 27 | // emit with argument 28 | emit('response', 'hello from child') 29 | } 30 | } 31 | ``` 32 | 33 |
    34 | 35 |
    36 | 37 |
    38 | 39 | ```js 40 | export default { 41 | // declare emitted events 42 | emits: ['response'], 43 | created() { 44 | // emit with argument 45 | this.$emit('response', 'hello from child') 46 | } 47 | } 48 | ``` 49 | 50 |
    51 | 52 | `this.$emit()``emit()` এর প্রথম আর্গুমেন্ট হল ইভেন্টের নাম। কোন অতিরিক্ত আর্গুমেন্ট event listener পাস করা হয়. 53 | 54 | parent component `v-on` ব্যবহার করে child component এর ইভেন্ট শুনতে পারেন - এখানে হ্যান্ডলার চাইল্ড emit কলের কাছ থেকে অতিরিক্ত আর্গুমেন্ট গ্রহণ করে এবং এটি local state এ বরাদ্দ করে: 55 | 56 |
    57 | 58 | ```vue-html 59 | 60 | ``` 61 | 62 |
    63 |
    64 | 65 | ```vue-html 66 | 67 | ``` 68 | 69 |
    70 | 71 | এখন এডিটরে নিজেই চেষ্টা করে দেখুন। 72 | -------------------------------------------------------------------------------- /src/tutorial/src/step-14/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | import ChildComp from './ChildComp.vue' 3 | 4 | export default { 5 | components: { 6 | ChildComp 7 | }, 8 | setup() { 9 | const msg = ref('from parent') 10 | 11 | return { 12 | msg 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/tutorial/src/step-14/App/options.js: -------------------------------------------------------------------------------- 1 | import ChildComp from './ChildComp.vue' 2 | 3 | export default { 4 | components: { 5 | ChildComp 6 | }, 7 | data() { 8 | return { 9 | msg: 'from parent' 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-14/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-14/ChildComp/template.html: -------------------------------------------------------------------------------- 1 | Fallback content 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-14/_hint/App/template.html: -------------------------------------------------------------------------------- 1 | Message: {{ msg }} 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-14/description.md: -------------------------------------------------------------------------------- 1 | # Slots {#slots} 2 | 3 | props এর মাধ্যমে data পাঠানোর পাশাপাশি, মূল কম্পোনেন্ট **slots**-এর মাধ্যমে child এর কাছে টেমপ্লেটের টুকরোগুলিও পাঠাতে পারে: 4 | 5 |
    6 | 7 | ```vue-html 8 | 9 | This is some slot content! 10 | 11 | ``` 12 | 13 |
    14 |
    15 | 16 | ```vue-html 17 | 18 | This is some slot content! 19 | 20 | ``` 21 | 22 |
    23 | 24 | চাইল্ড কম্পোনেন্টে, এটি আউটলেট হিসাবে `` কম্পোনেন্ট ব্যবহার করে parent এর কাছ থেকে স্লট সামগ্রী রেন্ডার করতে পারে: 25 | 26 |
    27 | 28 | ```vue-html 29 | 30 | 31 | ``` 32 | 33 |
    34 |
    35 | 36 | ```vue-html 37 | 38 | 39 | ``` 40 | 41 |
    42 | 43 | `` আউটলেটের ভিতরের বিষয়অবজেক্টকে "ফলব্যাক" বিষয়অবজেক্ট হিসেবে গণ্য করা হবে: যদি parent কোনো স্লট বিষয়অবজেক্ট না দিয়ে থাকেন তাহলে এটি প্রদর্শিত হবে: 44 | 45 | ```vue-html 46 | Fallback content 47 | ``` 48 | 49 | বর্তমানে আমরা ``-এ কোনো slot সামগ্রী পাঠাচ্ছি না, তাই আপনার ফলব্যাক সামগ্রী দেখতে হবে। parent's `msg` state ব্যবহার করার সময় child এ কিছু স্লট সামগ্রী প্রদান করা যাক। 50 | -------------------------------------------------------------------------------- /src/tutorial/src/step-15/App/composition.js: -------------------------------------------------------------------------------- 1 | import JSConfetti from 'js-confetti' 2 | 3 | const confetti = new JSConfetti() 4 | 5 | export default { 6 | setup() { 7 | function showConfetti() { 8 | confetti.addConfetti() 9 | } 10 | 11 | showConfetti() 12 | 13 | return { 14 | showConfetti 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/tutorial/src/step-15/App/options.js: -------------------------------------------------------------------------------- 1 | import JSConfetti from 'js-confetti' 2 | 3 | const confetti = new JSConfetti() 4 | 5 | export default { 6 | mounted() { 7 | this.showConfetti() 8 | }, 9 | methods: { 10 | showConfetti() { 11 | confetti.addConfetti() 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/tutorial/src/step-15/App/style.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | text-align: center; 3 | cursor: pointer; 4 | margin-top: 3em; 5 | } 6 | -------------------------------------------------------------------------------- /src/tutorial/src/step-15/App/template.html: -------------------------------------------------------------------------------- 1 |

    🎉 Congratulations!

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-15/description.md: -------------------------------------------------------------------------------- 1 | # You Did It! {#you-did-it} 2 | 3 | আপনি টিউটোরিয়াল শেষ করেছেন! 4 | 5 | এই মুহুর্তে, Vue এর সাথে কাজ করতে কেমন লাগে সে সম্পর্কে আপনার ভাল ধারণা থাকা উচিত। যাইহোক, আমরা অনেক কিছু সত্যিই দ্রুত কভার করেছি এবং বিশদ বিবরণে গ্লস করেছি, তাই অবশ্যই শিখতে থাকুন! পরবর্তী পদক্ষেপ হিসাবে, আপনি করতে পারেন: 6 | 7 | - [দ্রুত শুরু](/guide/quick-start) অনুসরণ করে আপনার মেশিনে একটি বাস্তব Vue প্রকল্প সেট আপ করুন। 8 | 9 | - [প্রধান নির্দেশিকা](/guide/essentials/application) এর মধ্য দিয়ে যান, যা আমরা এখন পর্যন্ত যে সমস্ত বিষয় শিখেছি তা আরও বিশদে এবং আরও অনেক কিছু কভার করে। 10 | 11 | - আরও কিছু ব্যবহারিক [উদাহরণ](/examples/) দেখুন। 12 | 13 | আপনার পরবর্তী নির্মাণ কি দেখতে আমরা অপেক্ষা করতে পারছিনা! 14 | -------------------------------------------------------------------------------- /src/tutorial/src/step-15/import-map.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "js-confetti": "https://cdn.jsdelivr.net/npm/js-confetti/+esm" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/tutorial/src/step-2/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | // component logic 6 | // declare some reactive state here. 7 | 8 | return { 9 | // exposed to template 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-2/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // component options 3 | // declare some reactive state here. 4 | } 5 | -------------------------------------------------------------------------------- /src/tutorial/src/step-2/App/template.html: -------------------------------------------------------------------------------- 1 |

    Make me dynamic!

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-2/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { reactive, ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const counter = reactive({ count: 0 }) 6 | const message = ref('Hello World!') 7 | 8 | return { 9 | counter, 10 | message 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/tutorial/src/step-2/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | message: 'Hello World!', 5 | counter: { 6 | count: 0 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/tutorial/src/step-2/_hint/App/template.html: -------------------------------------------------------------------------------- 1 |

    {{ message }}

    2 |

    Count is: {{ counter.count }}

    3 | -------------------------------------------------------------------------------- /src/tutorial/src/step-3/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const titleClass = ref('title') 6 | 7 | return { 8 | titleClass 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/tutorial/src/step-3/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | titleClass: 'title' 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/tutorial/src/step-3/App/style.css: -------------------------------------------------------------------------------- 1 | .title { 2 | color: red; 3 | } 4 | -------------------------------------------------------------------------------- /src/tutorial/src/step-3/App/template.html: -------------------------------------------------------------------------------- 1 |

    Make me red

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-3/_hint/App/template.html: -------------------------------------------------------------------------------- 1 |

    Make me red

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-3/description.md: -------------------------------------------------------------------------------- 1 | # Attribute Bindings {#attribute-bindings} 2 | 3 | Vue-তে, গোঁফগুলি শুধুমাত্র টেক্সট ইন্টারপোলেশনের জন্য ব্যবহৃত হয়। একটি গতিশীল মানের সাথে একটি বৈশিষ্ট্য আবদ্ধ করতে, আমরা `v-bind` নির্দেশ ব্যবহার করি: 4 | 5 | ```vue-html 6 |
    7 | ``` 8 | 9 | একটি **directive** হল একটি বিশেষ বৈশিষ্ট্য যা `v-` প্রিফিক্স দিয়ে শুরু হয়। তারা Vue এর টেমপ্লেট সিনট্যাক্সের অংশ। টেক্সট ইন্টারপোলেশনের মতোই, নির্দেশমূলক মান হল জাভাস্ক্রিপ্ট এক্সপ্রেশন যা কম্পোনেন্টের অবস্থায় অ্যাক্সেস করতে পারে। `v-bind` এবং নির্দেশমূলক সিনট্যাক্সের সম্পূর্ণ বিবরণ গাইড - টেমপ্লেট সিনট্যাক্স-এ আলোচনা করা হয়েছে। 10 | 11 | কোলনের পরের অংশ (`:id`) নির্দেশের "আর্গুমেন্ট"। এখানে, কম্পোনেন্টটির `id` বৈশিষ্ট্যটি কম্পোনেন্টটির অবস্থা থেকে `dynamicId` বৈশিষ্ট্যের সাথে সিঙ্ক করা হবে। 12 | 13 | কারণ `v-bind` প্রায়শই ব্যবহৃত হয়, এটির একটি ডেডিকেটেড শর্টহ্যান্ড সিনট্যাক্স রয়েছে: 14 | 15 | ```vue-html 16 |
    17 | ``` 18 | 19 | এখন, `titleClass` ডেটা প্রপার্টি ব্যবহার করে `

    `-এ একটি ডাইনামিক `ক্লাস` বাইন্ডিং যোগ করার চেষ্টা করুন ref এর মান হিসাবে। এটি সঠিকভাবে আবদ্ধ হলে, পাঠ্যটি লাল হওয়া উচিত। 20 | -------------------------------------------------------------------------------- /src/tutorial/src/step-4/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const count = ref(0) 6 | 7 | return { 8 | count 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/tutorial/src/step-4/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | count: 0 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/tutorial/src/step-4/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/tutorial/src/step-4/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const count = ref(0) 6 | 7 | function increment() { 8 | count.value++ 9 | } 10 | 11 | return { 12 | count, 13 | increment 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/tutorial/src/step-4/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | count: 0 5 | } 6 | }, 7 | methods: { 8 | increment() { 9 | this.count++ 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-4/_hint/App/template.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-5/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const text = ref('') 6 | 7 | function onInput(e) { 8 | text.value = e.target.value 9 | } 10 | 11 | return { 12 | text, 13 | onInput 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/tutorial/src/step-5/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | text: '' 5 | } 6 | }, 7 | methods: { 8 | onInput(e) { 9 | this.text = e.target.value 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-5/App/template.html: -------------------------------------------------------------------------------- 1 | 2 |

    {{ text }}

    3 | -------------------------------------------------------------------------------- /src/tutorial/src/step-5/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const text = ref('') 6 | 7 | return { 8 | text 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/tutorial/src/step-5/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | text: '' 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/tutorial/src/step-5/_hint/App/template.html: -------------------------------------------------------------------------------- 1 | 2 |

    {{ text }}

    3 | -------------------------------------------------------------------------------- /src/tutorial/src/step-5/description.md: -------------------------------------------------------------------------------- 1 | # Form Bindings {#form-bindings} 2 | 3 | `v-bind` এবং `v-on` একসাথে ব্যবহার করে, আমরা form ইনপুট কম্পোনেন্টগুলিতে দ্বি-মুখী বাইন্ডিং তৈরি করতে পারি: 4 | 5 | ```vue-html 6 | 7 | ``` 8 | 9 |
    10 | 11 | ```js 12 | methods: { 13 | onInput(e) { 14 | // a v-on handler receives the native DOM event 15 | // as the argument. 16 | this.text = e.target.value 17 | } 18 | } 19 | ``` 20 | 21 |
    22 | 23 |
    24 | 25 | ```js 26 | function onInput(e) { 27 | // a v-on handler receives the native DOM event 28 | // as the argument. 29 | text.value = e.target.value 30 | } 31 | ``` 32 | 33 |
    34 | 35 | ইনপুট বাক্সে টাইপ করার চেষ্টা করুন - আপনি টাইপ করার সাথে সাথে আপডেট হওয়া `

    `-এ পাঠ্য দেখতে পাবেন। 36 | 37 | দ্বি-মুখী বাইন্ডিং সহজ করার জন্য, Vue একটি নির্দেশিকা প্রদান করে, `v-model`, যা মূলত উপরের জন্য সিনট্যাকটিক চিনি: 38 | 39 | ```vue-html 40 | 41 | ``` 42 | 43 | `v-model` স্বয়ংক্রিয়ভাবে `` এর মানকে আবদ্ধ অবস্থার সাথে সিঙ্ক করে, তাই এর জন্য আমাদের আর কোনো ইভেন্ট হ্যান্ডলার ব্যবহার করতে হবে না। 44 | 45 | `v-model` শুধুমাত্র টেক্সট ইনপুট নয়, অন্যান্য ইনপুট ধরনের যেমন চেকবক্স, রেডিও বোতাম এবং নির্বাচিত ড্রপডাউনগুলিতেও কাজ করে। আমরা গাইড - ফর্ম বাইন্ডিং-এ আরও বিশদ বিবরণ কভার করি। 46 | 47 | এখন, পরিবর্তে `v-model` ব্যবহার করতে কোডটিকে রিফ্যাক্টর করার চেষ্টা করুন। 48 | -------------------------------------------------------------------------------- /src/tutorial/src/step-6/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const awesome = ref(true) 6 | 7 | function toggle() { 8 | // ... 9 | } 10 | 11 | return { 12 | awesome, 13 | toggle 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/tutorial/src/step-6/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | awesome: true 5 | } 6 | }, 7 | methods: { 8 | toggle() { 9 | // ... 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-6/App/template.html: -------------------------------------------------------------------------------- 1 | 2 |

    Vue is awesome!

    3 |

    Oh no 😢

    4 | -------------------------------------------------------------------------------- /src/tutorial/src/step-6/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const awesome = ref(true) 6 | 7 | function toggle() { 8 | awesome.value = !awesome.value 9 | } 10 | 11 | return { 12 | awesome, 13 | toggle 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/tutorial/src/step-6/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data() { 3 | return { 4 | awesome: true 5 | } 6 | }, 7 | methods: { 8 | toggle() { 9 | this.awesome = !this.awesome 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/tutorial/src/step-6/_hint/App/template.html: -------------------------------------------------------------------------------- 1 | 2 |

    Vue is awesome!

    3 |

    Oh no 😢

    4 | -------------------------------------------------------------------------------- /src/tutorial/src/step-6/description.md: -------------------------------------------------------------------------------- 1 | # Conditional Rendering {#conditional-rendering} 2 | 3 | শর্তসাপেক্ষে একটি কম্পোনেন্ট রেন্ডার করতে আমরা `v-if` নির্দেশ ব্যবহার করতে পারি: 4 | 5 | ```vue-html 6 |

    Vue is awesome!

    7 | ``` 8 | 9 | এই `

    ` শুধুমাত্র যদি `awesome` এর মান [সত্য](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) হয় তবেই রেন্ডার করা হবে। যদি `awesome` একটি [মিথ্যা](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) মানতে পরিবর্তিত হয়, তাহলে এটি DOM থেকে সরানো হবে। 10 | 11 | আমরা শর্তের অন্যান্য শাখাগুলি বোঝাতে `v-else` এবং `v-else-if` ব্যবহার করতে পারি: 12 | 13 | ```vue-html 14 |

    Vue is awesome!

    15 |

    Oh no 😢

    16 | ``` 17 | 18 | বর্তমানে, ডেমো একই সময়ে `

    ` উভয়ই দেখাচ্ছে, এবং বোতাম কিছুই করে না। তাদের সাথে `v-if` এবং `v-else` নির্দেশাবলী যোগ করার চেষ্টা করুন এবং `toggle()` পদ্ধতিটি প্রয়োগ করুন যাতে আমরা তাদের মধ্যে টগল করতে বোতামটি ব্যবহার করতে পারি। 19 | 20 | `v-if` বিষয়ে আরও বিশদ বিবরণ: গাইড - শর্তসাপেক্ষ রেন্ডারিং 21 | -------------------------------------------------------------------------------- /src/tutorial/src/step-7/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | // give each todo a unique id 6 | let id = 0 7 | 8 | const newTodo = ref('') 9 | const todos = ref([ 10 | { id: id++, text: 'Learn HTML' }, 11 | { id: id++, text: 'Learn JavaScript' }, 12 | { id: id++, text: 'Learn Vue' } 13 | ]) 14 | 15 | function addTodo() { 16 | // ... 17 | newTodo.value = '' 18 | } 19 | 20 | function removeTodo(todo) { 21 | // ... 22 | } 23 | 24 | return { 25 | newTodo, 26 | todos, 27 | addTodo, 28 | removeTodo 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/tutorial/src/step-7/App/options.js: -------------------------------------------------------------------------------- 1 | // give each todo a unique id 2 | let id = 0 3 | 4 | export default { 5 | data() { 6 | return { 7 | newTodo: '', 8 | todos: [ 9 | { id: id++, text: 'Learn HTML' }, 10 | { id: id++, text: 'Learn JavaScript' }, 11 | { id: id++, text: 'Learn Vue' } 12 | ] 13 | } 14 | }, 15 | methods: { 16 | addTodo() { 17 | // ... 18 | this.newTodo = '' 19 | }, 20 | removeTodo(todo) { 21 | // ... 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/tutorial/src/step-7/App/template.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 |
      6 |
    • 7 | {{ todo.text }} 8 | 9 |
    • 10 |
    11 | -------------------------------------------------------------------------------- /src/tutorial/src/step-7/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | // give each todo a unique id 6 | let id = 0 7 | 8 | const newTodo = ref('') 9 | const todos = ref([ 10 | { id: id++, text: 'Learn HTML' }, 11 | { id: id++, text: 'Learn JavaScript' }, 12 | { id: id++, text: 'Learn Vue' } 13 | ]) 14 | 15 | function addTodo() { 16 | todos.value.push({ id: id++, text: newTodo.value }) 17 | newTodo.value = '' 18 | } 19 | 20 | function removeTodo(todo) { 21 | todos.value = todos.value.filter((t) => t !== todo) 22 | } 23 | 24 | return { 25 | newTodo, 26 | todos, 27 | addTodo, 28 | removeTodo 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/tutorial/src/step-7/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | // give each todo a unique id 2 | let id = 0 3 | 4 | export default { 5 | data() { 6 | return { 7 | newTodo: '', 8 | todos: [ 9 | { id: id++, text: 'Learn HTML' }, 10 | { id: id++, text: 'Learn JavaScript' }, 11 | { id: id++, text: 'Learn Vue' } 12 | ] 13 | } 14 | }, 15 | methods: { 16 | addTodo() { 17 | this.todos.push({ id: id++, text: this.newTodo }) 18 | this.newTodo = '' 19 | }, 20 | removeTodo(todo) { 21 | this.todos = this.todos.filter((t) => t !== todo) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/tutorial/src/step-8/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | let id = 0 6 | 7 | const newTodo = ref('') 8 | const hideCompleted = ref(false) 9 | const todos = ref([ 10 | { id: id++, text: 'Learn HTML', done: true }, 11 | { id: id++, text: 'Learn JavaScript', done: true }, 12 | { id: id++, text: 'Learn Vue', done: false } 13 | ]) 14 | 15 | function addTodo() { 16 | todos.value.push({ id: id++, text: newTodo.value, done: false }) 17 | newTodo.value = '' 18 | } 19 | 20 | function removeTodo(todo) { 21 | todos.value = todos.value.filter((t) => t !== todo) 22 | } 23 | 24 | return { 25 | newTodo, 26 | hideCompleted, 27 | todos, 28 | addTodo, 29 | removeTodo 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/tutorial/src/step-8/App/options.js: -------------------------------------------------------------------------------- 1 | let id = 0 2 | 3 | export default { 4 | data() { 5 | return { 6 | newTodo: '', 7 | hideCompleted: false, 8 | todos: [ 9 | { id: id++, text: 'Learn HTML', done: true }, 10 | { id: id++, text: 'Learn JavaScript', done: true }, 11 | { id: id++, text: 'Learn Vue', done: false } 12 | ] 13 | } 14 | }, 15 | computed: { 16 | // ... 17 | }, 18 | methods: { 19 | addTodo() { 20 | this.todos.push({ id: id++, text: this.newTodo, done: false }) 21 | this.newTodo = '' 22 | }, 23 | removeTodo(todo) { 24 | this.todos = this.todos.filter((t) => t !== todo) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/tutorial/src/step-8/App/style.css: -------------------------------------------------------------------------------- 1 | .done { 2 | text-decoration: line-through; 3 | } 4 | -------------------------------------------------------------------------------- /src/tutorial/src/step-8/App/template.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 |
      6 |
    • 7 | 8 | {{ todo.text }} 9 | 10 |
    • 11 |
    12 | 15 | -------------------------------------------------------------------------------- /src/tutorial/src/step-8/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | let id = 0 6 | 7 | const newTodo = ref('') 8 | const hideCompleted = ref(false) 9 | const todos = ref([ 10 | { id: id++, text: 'Learn HTML', done: true }, 11 | { id: id++, text: 'Learn JavaScript', done: true }, 12 | { id: id++, text: 'Learn Vue', done: false } 13 | ]) 14 | 15 | const filteredTodos = computed(() => { 16 | return hideCompleted.value 17 | ? todos.value.filter((t) => !t.done) 18 | : todos.value 19 | }) 20 | 21 | function addTodo() { 22 | todos.value.push({ id: id++, text: newTodo.value, done: false }) 23 | newTodo.value = '' 24 | } 25 | 26 | function removeTodo(todo) { 27 | todos.value = todos.value.filter((t) => t !== todo) 28 | } 29 | 30 | return { 31 | newTodo, 32 | hideCompleted, 33 | todos, 34 | filteredTodos, 35 | addTodo, 36 | removeTodo 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/tutorial/src/step-8/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | let id = 0 2 | 3 | export default { 4 | data() { 5 | return { 6 | newTodo: '', 7 | hideCompleted: false, 8 | todos: [ 9 | { id: id++, text: 'Learn HTML', done: true }, 10 | { id: id++, text: 'Learn JavaScript', done: true }, 11 | { id: id++, text: 'Learn Vue', done: false } 12 | ] 13 | } 14 | }, 15 | computed: { 16 | filteredTodos() { 17 | return this.hideCompleted 18 | ? this.todos.filter((t) => !t.done) 19 | : this.todos 20 | } 21 | }, 22 | methods: { 23 | addTodo() { 24 | this.todos.push({ id: id++, text: this.newTodo, done: false }) 25 | this.newTodo = '' 26 | }, 27 | removeTodo(todo) { 28 | this.todos = this.todos.filter((t) => t !== todo) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/tutorial/src/step-8/_hint/App/template.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 |
      6 |
    • 7 | 8 | {{ todo.text }} 9 | 10 |
    • 11 |
    12 | 15 | -------------------------------------------------------------------------------- /src/tutorial/src/step-9/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const pElementRef = ref(null) 6 | 7 | return { 8 | pElementRef 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/tutorial/src/step-9/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | // ... 3 | } 4 | -------------------------------------------------------------------------------- /src/tutorial/src/step-9/App/template.html: -------------------------------------------------------------------------------- 1 |

    Hello

    2 | -------------------------------------------------------------------------------- /src/tutorial/src/step-9/_hint/App/composition.js: -------------------------------------------------------------------------------- 1 | import { ref, onMounted } from 'vue' 2 | 3 | export default { 4 | setup() { 5 | const pElementRef = ref(null) 6 | 7 | onMounted(() => { 8 | pElementRef.value.textContent = 'mounted!' 9 | }) 10 | 11 | return { 12 | pElementRef 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/tutorial/src/step-9/_hint/App/options.js: -------------------------------------------------------------------------------- 1 | export default { 2 | mounted() { 3 | this.$refs.pElementRef.textContent = 'mounted!' 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/tutorial/tutorial.data.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { createMarkdownRenderer } from 'vitepress' 3 | import { readExamples, ExampleData } from '../examples/examples.data' 4 | 5 | export declare const data: Record 6 | 7 | export default { 8 | watch: './src/**', 9 | async load() { 10 | const md = await createMarkdownRenderer(process.cwd(), { 11 | theme: 'github-dark', 12 | }, '/') 13 | const files = readExamples(path.resolve(__dirname, './src')) 14 | for (const step in files) { 15 | const stepFiles = files[step] 16 | const desc = stepFiles['description.md'] as string 17 | if (desc) { 18 | stepFiles['description.md'] = md.render(desc) 19 | } 20 | } 21 | return files 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "target": "esnext", 5 | "module": "esnext", 6 | "moduleResolution": "bundler", 7 | "esModuleInterop": true, 8 | "resolveJsonModule": true, 9 | "allowJs": true, 10 | "strict": true, 11 | "noUnusedLocals": true, 12 | "skipLibCheck": true, 13 | "jsx": "preserve", 14 | "baseUrl": ".", 15 | "paths": { 16 | "@theme/*": [".vitepress/theme/*"] 17 | } 18 | }, 19 | "include": ["env.d.ts", "src/**/*", ".vitepress/**/*"] 20 | } 21 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://openapi.vercel.sh/vercel.json", 3 | "headers": [ 4 | { 5 | "source": "/assets/(.*)", 6 | "headers": [ 7 | { 8 | "key": "Cache-Control", 9 | "value": "max-age=31536000, immutable" 10 | } 11 | ] 12 | }, 13 | { 14 | "source": "/(.*).png", 15 | "headers": [ 16 | { 17 | "key": "Cache-Control", 18 | "value": "max-age=604800, immutable" 19 | } 20 | ] 21 | } 22 | ], 23 | "rewrites": [ 24 | { 25 | "source": "/:path*", 26 | "destination": "/:path*.html" 27 | } 28 | ] 29 | } 30 | --------------------------------------------------------------------------------