documentation/frontend: Create "Add link" onboarding dialog demo

Add an OnboardingDialog component that can be reused for the different onboarding dialogs.
Includes an Onboarding paginator to show progress in the dialog.
AddLinkDialog includes an OnboardingDialog component and
an OnboardingStep component for each step of the dialog.

A demo of this component can be seen in
https://doc.wikimedia.org/GrowthExperiments/master/js/frontend/

Bug: T329037
Change-Id: I57dc528edc648cd7fc726ac22e53f3adcfb3d7fa
这个提交包含在:
vyanez 2023-03-08 13:43:04 +01:00
父节点 259f894317
当前提交 1a90a37ba3
共有 12 个文件被更改,包括 721 次插入517 次删除

查看文件

@ -23,7 +23,7 @@ module.exports = function ( grunt ) {
stylelint: {
all: [
'modules/**/*.{less,vue}',
'documentation/frontend/component-demos/**/*.{less,vue}'
'documentation/frontend/{component-demos,components}/**/*.{less,vue}'
]
},
banana: {

查看文件

@ -0,0 +1,37 @@
<template>
<div>
<cdx-button @click="open = true">
Show Add link Dialog
</cdx-button>
<!-- eslint-disable vue/no-v-model-argument -->
<add-link-dialog
v-model:open="open"
@default="open = false">
</add-link-dialog>
</div>
</template>
<script>
import { CdxButton } from '@wikimedia/codex';
import AddLinkDialog from '../../components/AddLinkDialog.vue';
import { ref } from 'vue';
export default {
name: 'AddLinkDialogDemo',
components: {
AddLinkDialog,
CdxButton
},
setup() {
const open = ref( false );
return {
open
};
}
};
</script>

查看文件

@ -0,0 +1,221 @@
<template>
<!-- eslint-disable vue/no-v-model-argument -->
<onboarding-dialog
v-model:open="open"
v-model="modelValue"
:total-steps="3"
:initial-step="0"
@default="open = false"
>
<template #title>
Introduction
</template>
<template #headerbtntext>
Skip all
</template>
<template #body="{ currentIndex }">
<onboarding-step
:current-index="currentIndex"
:index="1"
>
<template #image>
<div
class="
ext-growthExperiments-AddLinkDialog__image
ext-growthExperiments-AddLinkDialog__image-1">
</div>
</template>
<template #header>
<h5 class="ext-growthExperiments-AddLinkDialog__text__title">
Adding links will help people learn faster.
</h5>
</template>
<template #main>
<p>
You will decide whether words in one Wikipedia article should link
to other Wikipedia articles.
</p>
<div
class="ext-growthExperiments-AddLinkDialog__text__label">
Example sentence
</div>
<div
class="
ext-growthExperiments-AddLinkDialog__text__example">
The moon is the only
<!-- eslint-disable-next-line max-len -->
<mark class="ext-growthExperiments-AddLinkDialog__text__example__highlighted">
natural satellite</mark> that
<mark
class="
ext-growthExperiments-AddLinkDialog__text__example__highlighted">
orbits</mark> around the
<mark
class="
ext-growthExperiments-AddLinkDialog__text__example__highlighted">
Earth</mark>.
</div>
<p>
No special knowledge about the article is needed to do this task.
</p>
</template>
</onboarding-step>
<onboarding-step
learn-more-link="Learn more about machine suggestions"
:index="2"
:current-index="currentIndex">
<template #image>
<div
class="
ext-growthExperiments-AddLinkDialog__image
ext-growthExperiments-AddLinkDialog__image-2">
</div>
</template>
<template #header>
<h5 class="ext-growthExperiments-AddLinkDialog__text__title">
Suggested links are machine-generated, and can be incorrect.
</h5>
</template>
<template #main>
<!-- eslint-disable-next-line max-len -->
<p>The suggestions might be on words that dont need them, or might link to the wrong article. Use your judgment to decide whether they are right or wrong.</p>
</template>
</onboarding-step>
<onboarding-step
:index="3"
:current-index="currentIndex">
<template #image>
<div
class="
ext-growthExperiments-AddLinkDialog__image
ext-growthExperiments-AddLinkDialog__image-3">
</div>
</template>
<template #header>
<h5 class="ext-growthExperiments-AddLinkDialog__text__title">
Guidelines
</h5>
</template>
<template #main>
<div class="ext-growthExperiments-AddLinkDialog__text__list">
<ul>
<li>Link concepts that a reader might want to learn more about.</li>
<li>Make sure the link is going to the right article.</li>
<li>Don't link common words, years, or dates.</li>
<li>If you're not sure, skip.</li>
</ul>
</div>
</template>
</onboarding-step>
</template>
<template #checkbox>
Don't show again
</template>
<template #last-step-button-text>
Get started
</template>
</onboarding-dialog>
</template>
<script>
import { ref } from 'vue';
import OnboardingDialog from './OnboardingDialog.vue';
import OnboardingStep from './OnboardingStep.vue';
export default {
name: 'AddLinkDialog',
components: {
OnboardingDialog,
OnboardingStep
},
props: {
},
setup() {
const modelValue = ref( false );
return {
modelValue,
open
};
}
};
</script>
<style lang="less">
@import '../node_modules/@wikimedia/codex-design-tokens/dist/theme-wikimedia-ui.less';
@import './variables.less';
.ext-growthExperiments-AddLinkDialog {
&__image {
height: 216px;
background-repeat: no-repeat;
background-position: center;
background-color: @onboardingBackgroundColor;
&-1 {
background-image: url( ../../../images/addlink/onboarding-image1-ltr.svg );
}
&-2 {
background-image: url( ../../../images/addlink/onboarding-image2-ltr.svg );
}
&-3 {
background-image: url( ../../../images/addlink/onboarding-image3-ltr.svg );
}
}
&__text {
&__title {
font-size: @font-size-medium;
line-height: @line-height-xx-small;
font-weight: @font-weight-bold;
}
&__label {
color: @color-placeholder;
font-size: @font-size-x-small;
line-height: @line-height-xx-small;
font-style: italic;
margin-top: @spacing-50;
}
&__example {
padding: 12px;
background: @background-color-interactive-subtle;
// As discussed on https://phabricator.wikimedia.org/T332567
// this color is not a DS border-color yet
// and should be changed
border: 1px solid @onboardingExampleBorderColor;
box-sizing: border-box;
border-radius: @border-radius-base;
margin-bottom: @spacing-50;
line-height: @line-height-xx-small;
font-size: @font-size-small;
&__highlighted {
background-color: @background-color-progressive-subtle;
}
}
&__list {
ul {
list-style: inside;
margin-left: @spacing-50;
li {
margin-top: 8px;
}
}
}
}
}
</style>

查看文件

@ -0,0 +1,269 @@
<template>
<!-- eslint-disable vue/no-v-model-argument -->
<!-- The provided header from Codex Dialog is hidden in order to
provide a custom header with the title and a button -->
<cdx-dialog
v-model:open="open"
class="ext-growthExperiments-OnboardingDialog"
title="Onboarding Dialog"
:hide-title="true"
@update:open="{ $emit( 'update:open', false ); currentIndex = initialStep }"
>
<!-- Custom Dialog Header -->
<div class="ext-growthExperiments-OnboardingDialog__header">
<!-- Slot for dialog title -->
<h5 class="ext-growthExperiments-OnboardingDialog__header__title">
<slot name="title"></slot>
</h5>
<!-- Header button that will display in all steps except last one
if slot with inner text is provided -->
<div>
<cdx-button
v-if="$slots.headerbtntext && currentIndex !== totalSteps - 1"
weight="quiet"
@click="$emit( 'update:open', false ); currentIndex = initialStep"
>
<slot name="headerbtntext" :current-index="currentIndex"></slot>
</cdx-button>
</div>
</div>
<!-- Dialog Content -->
<div class="ext-growthExperiments-OnboardingDialog__content">
<!-- Dialog paginator indicate current steps and total steps -->
<div class="ext-growthExperiments-OnboardingDialog__content__fixed-content">
<onboarding-paginator
:total-steps="totalSteps"
:current-step="currentIndex + 1 "
>
</onboarding-paginator>
</div>
<div class="ext-growthExperiments-OnboardingDialog__content__body">
<!-- This slot contains the content for the different steps in the dialog.
The content for each step must be wrapped into a OnboardingStep component -->
<slot name="body" :current-index="currentIndex">
</slot>
</div>
</div>
<!-- Dialog Footer -->
<div class="ext-growthExperiments-OnboardingDialog__footer">
<div
class="ext-growthExperiments-OnboardingDialog__footer__actions"
>
<!-- Footer Actions Prev -->
<!-- The first step of the dialog displays a checkbox
if text content for the slot label is provided.
The checkbox value can be accesed by v-model:checkboxValue -->
<div
v-if="currentIndex === 0"
class="ext-growthExperiments-OnboardingDialog__footer__actions-prev">
<!-- eslint-disable-next-line max-len -->
<cdx-checkbox
v-if="$slots.checkbox"
v-model="modelValue"
:value="modelValue"
@update:model-value="$emit( 'update:modelValue', modelValue )"
>
<slot name="checkbox">
</slot>
</cdx-checkbox>
</div>
<!-- All the following steps display an Icon only button to navigate
to the previous step -->
<div
v-else
class="ext-growthExperiments-OnboardingDialog__footer__actions-prev">
<cdx-button
aria-label="previous"
@click="onPrevClick">
<cdx-icon :icon="cdxIconPrevious" icon-label="previous"></cdx-icon>
</cdx-button>
</div>
<!-- Footer Acctions Next -->
<!-- The last step displays a button with a slot for the text content -->
<div
v-if="currentIndex + 1 === totalSteps"
class="ext-growthExperiments-OnboardingDialog__footer__actions-next">
<cdx-button
weight="primary"
action="progressive"
@click="$emit( 'update:open', false ); currentIndex = initialStep">
<slot name="last-step-button-text"></slot>
</cdx-button>
</div>
<!-- All the previous steps display an Icon only button to navigate
to the next step -->
<div
v-else
class="ext-growthExperiments-OnboardingDialog__footer__actions-next">
<cdx-button
weight="primary"
action="progressive"
class="cdx-button--icon-only"
aria-label="next"
@click="onNextClick">
<cdx-icon :icon="cdxIconNext" icon-label="next"></cdx-icon>
</cdx-button>
</div>
</div>
</div>
</cdx-dialog>
</template>
<script>
import { CdxDialog, CdxButton, CdxIcon, CdxCheckbox } from '@wikimedia/codex';
import { cdxIconNext, cdxIconPrevious } from '@wikimedia/codex-icons';
import OnboardingPaginator from './OnboardingPaginator.vue';
import { ref } from 'vue';
export default {
name: 'OnboardingDialog',
components: {
CdxDialog,
CdxButton,
CdxIcon,
CdxCheckbox,
OnboardingPaginator
},
props: {
/**
* The total number of steps the dialog displays
*/
totalSteps: {
type: Number,
default: 0
},
/**
* First step to show when the dialog open
*/
initialStep: {
type: Number,
default: 0
}
},
emits: [ 'update:open', 'update:modelValue' ],
setup( props, { modelValue } ) {
const currentIndex = ref( props.initialStep );
const onNextClick = () => {
if ( currentIndex.value + 1 < props.totalSteps ) {
currentIndex.value++;
}
};
const onPrevClick = () => {
if ( currentIndex.value > 0 ) {
currentIndex.value--;
}
};
return {
currentIndex,
onNextClick,
onPrevClick,
cdxIconNext,
cdxIconPrevious,
open,
modelValue
};
}
};
</script>
<style lang="less">
@import '../node_modules/@wikimedia/codex-design-tokens/dist/theme-wikimedia-ui.less';
@import './variables.less';
.ext-growthExperiments-OnboardingDialog {
// Overwrite Codex's vertical gutter on SimpleDialog
// stylelint-disable-next-line selector-class-pattern
> .cdx-dialog {
height: 520px;
padding-top: 0;
padding-bottom: 0;
color: @color-base;
// Overwrite Codex's horizontal padding on SimpleDialog
// stylelint-disable-next-line selector-class-pattern
.cdx-dialog__body {
padding-left: 0;
padding-right: 0;
margin-top: 0;
margin-bottom: 0;
}
// Overwrite the Codex Dialog size on small screens
// to get fullscreen widht and height on mobile
@media ( max-width: 499px ) {
width: 100%;
height: 100%;
border: 0;
box-shadow: none;
position: absolute;
top: 0;
.ext-growthExperiments-OnboardingDialog__footer {
position: fixed;
bottom: 0;
width: 100%;
}
}
.ext-growthExperiments-OnboardingDialog {
&__header {
display: flex;
justify-content: space-between;
// This is the background color for the AddlinkDialog Images
// and should be replaced as discussed on
// https://phabricator.wikimedia.org/T332567
// with a DS background color
background-color: @onboardingBackgroundColor;
&__title {
font-size: @font-size-medium;
line-height: 2.72em;
font-weight: @font-weight-bold;
min-height: @size-275;
padding-left: @spacing-75;
padding-right: @spacing-75;
}
}
&__content {
&__fixed-content {
padding-left: @spacing-75;
padding-right: @spacing-75;
position: absolute;
z-index: 1;
}
}
&__footer {
border-top: @border-width-base @border-style-base @border-color-base;
padding: @spacing-75 @spacing-100;
&__actions {
display: flex;
align-items: center;
justify-content: space-between;
font-size: @font-size-small;
}
}
}
}
}
</style>

查看文件

@ -0,0 +1,57 @@
<template>
<div class="ext-growthExperiments-OnboardingPaginator">
<div class="ext-growthExperiments-OnboardingPaginator__dots">
<div
v-for="step in [ ...Array( totalSteps ).keys() ]"
:key="step"
class="ext-growthExperiments-OnboardingPaginator__dots__dot"
:class="
{ 'ext-growthExperiments-OnboardingPaginator__dots__dot--active':
step < currentStep }"
></div>
</div>
<p>{{ currentStep }} of {{ totalSteps }}</p>
</div>
</template>
<script>
export default {
name: 'OnboardingPaginator',
props: {
totalSteps: { type: Number, default: 0 },
currentStep: { type: Number, default: 0 }
},
setup() {}
};
</script>
<style lang="less">
@import '../node_modules/@wikimedia/codex-design-tokens/dist/theme-wikimedia-ui.less';
.ext-growthExperiments-OnboardingPaginator {
display: flex;
font-size: @font-size-x-small;
color: @color-subtle;
&__dots {
display: flex;
align-items: center;
&__dot {
background-color: @color-emphasized;
background-color: @background-color-disabled;
border-radius: 50%;
width: 8px;
height: 8px;
margin-right: @spacing-50;
&--active {
background-color: #202122;
}
}
}
}
</style>

查看文件

@ -0,0 +1,72 @@
<template>
<div
v-if="currentIndex + 1 === index"
class="ext-growthExperiments-ViewStep">
<div class="ext-growthExperiments-ViewStep__image">
<slot name="image"></slot>
</div>
<div class="ext-growthExperiments-ViewStep__text">
<div class="ext-growthExperiments-ViewStep__text__title">
<slot name="header"></slot>
</div>
<div class="ext-growthExperiments-ViewStep__text__paragraph">
<slot name="main">
</slot>
</div>
<a
v-if="learnMoreLink !== ''"
class="cdx-docs-link "
href="">{{ learnMoreLink }}</a>
</div>
</div>
</template>
<script>
export default {
name: 'OnboardingStep',
props: {
index: {
type: Number,
default: 0
},
currentIndex: {
type: Number,
default: 0
},
learnMoreLink: {
type: String,
default: ''
}
}
};
</script>
<style lang="less">
@import '../node_modules/@wikimedia/codex-design-tokens/dist/theme-wikimedia-ui.less';
@import '../node_modules/@wikimedia/codex/mixins/link.less';
// stylelint-disable-next-line selector-class-pattern
.cdx-docs-link {
.cdx-mixin-link();
}
.ext-growthExperiments-ViewStep {
&__text {
border-top: @border-width-base @border-style-base @border-color-base;
padding-top: @spacing-100;
padding-right: @spacing-100;
padding-left: @spacing-100;
min-height: 200px;
font-size: @font-size-small;
&__paragraph {
color: @color-base;
line-height: @line-height-xx-small;
margin: 0.4em 0 0.5em 0;
}
}
}
</style>

查看文件

@ -0,0 +1,3 @@
@onboardingBackgroundColor: #f4f9ff;
@onboardingExampleBorderColor: #eaecf0;

查看文件

@ -0,0 +1,25 @@
<!-- <link rel="stylesheet" href="../node_modules/@wikimedia/codex/dist/codex.style.css" /> -->
<script setup>
import '../../node_modules/@wikimedia/codex/dist/codex.style.css';
import AddLinkDialogDemo from '../../component-demos/add-link-dialog/AddLinkDialogDemo.vue'
</script>
Add a link dialog Vue prototype
===============================
When a newcomer starts an Add a link task a dialog is placed on top of visual editor giving the user detailed information in the steps to complete the task.
- This dialog has 3 steps which are navigable with arrows back and forth.
- The first step includes a "Don't show again" checkbox mark so users can check it to indicate they don't want the instructions dialog to show again when doing Add a link tasks.
- The last step includes a "Get started" button to close the dialog.
- The dialog can be closed at any step that is not the last one by the "Skip all" button at the top.
See the [Figma Design](https://www.figma.com/file/Pgo6fPGaDDiqXWGfMI8oiF/Growth---features?node-id=1271-97685).
::: raw
<AddLinkDialogDemo />
:::

查看文件

@ -3,10 +3,9 @@ import '../../node_modules/@wikimedia/codex/dist/codex.style.css';
import TopicSelectionDemo from '../../component-demos/topic-selection-dialog/TopicSelectionDemo.vue'
</script>
Topic selection dialog Vue prototype
====================================
# Topic selection dialog Vue prototype
This is a .md using a custom component
::: raw
<TopicSelectionDemo />
:::
:::

查看文件

@ -23,8 +23,9 @@ These are demos of components currently used in production.
These are not complete demonstrations, they exist only to showcase how one can
create demos for GrowthExperiments components.
- [Topic selection dialog](./demos/topic-selection-dialog)
- [Post edit dialog](./demos/post-edit-dialog)
- [Topic selection dialog](./demos/topic-selection-dialog)
- [Post edit dialog](./demos/post-edit-dialog)
- [Add Link dialog](./demos/add-link-dialog)
## Importing components into MediaWiki
@ -32,9 +33,10 @@ Due to MediaWiki's ResourceLoader constraints on ES modules usage and the
limited support for Vue SFCs in MediaWiki (see [Use_Single-file_components](https://www.mediawiki.org/wiki/Vue.js#Use_Single-file_components))
it's not possible to document the existing GrowthExperiments components
with VitePress. Therefore the existing components under:
- `/modules/vue-components`
- `/modules/ext.growthExperiments.MentorDashboard`
- `/modules/ext.growthExperiments.Homepage.NewImpact`
can't be directly imported into the __docs__ project. Alternatives to
- `/modules/vue-components`
- `/modules/ext.growthExperiments.MentorDashboard`
- `/modules/ext.growthExperiments.Homepage.NewImpact`
can't be directly imported into the **docs** project. Alternatives to
solve this problem are being considered in [Phab T328125](https://phabricator.wikimedia.org/T328125).

查看文件

@ -10,9 +10,9 @@
"devDependencies": {
"@vitejs/plugin-vue": "4.0.0",
"@vue/test-utils": "2.3.2",
"@wikimedia/codex": "0.6.1",
"@wikimedia/codex-design-tokens": "0.6.1",
"@wikimedia/codex-icons": "0.6.1",
"@wikimedia/codex": "0.7.0",
"@wikimedia/codex-design-tokens": "0.7.0",
"@wikimedia/codex-icons": "0.7.0",
"jsdom": "21.1.1",
"less": "2.5.3",
"postcss": "8.4.21",
@ -237,70 +237,6 @@
}
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
"integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
"integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
"integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
"integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
@ -317,278 +253,6 @@
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
"integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
"integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
"integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
"integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
"integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
"integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
"integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
"cpu": [
"mips64el"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
"integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
"integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
"integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
"integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
"integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
"integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
"integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
"integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
"integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
"integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@tootallnate/once": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
@ -598,6 +262,7 @@
"node": ">= 10"
}
},
"node_modules/@types/chai": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz",
@ -952,9 +617,9 @@
}
},
"node_modules/@wikimedia/codex": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.6.1.tgz",
"integrity": "sha512-WHc1+DfNSBuX0DNl0AxelbGQ5c8+9NQ9KbTLHLsrvPP1Fo06cOifsWjo8/0hRxfvwV7/uM9y1qeZ/2yyMdkw+A==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.7.0.tgz",
"integrity": "sha512-SEm9HkuAdfoTrC/tNcftiZU3ljSthYZRdgdFRENSsrgZjVtTeZ5Zr0MPxbTRaEBoeyOk8v1IY3VbgcSAgBdslQ==",
"dev": true,
"engines": {
"node": ">=16",
@ -965,9 +630,9 @@
}
},
"node_modules/@wikimedia/codex-design-tokens": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-design-tokens/-/codex-design-tokens-0.6.1.tgz",
"integrity": "sha512-mCkidhmkJ1iTDkK+Jwm3lShdI3ha6Zj8bvvof7Oc5//WMYShZ/YYJj6ryd0zdy0XOlNPf7PvKgSTiyaYuRduRQ==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-design-tokens/-/codex-design-tokens-0.7.0.tgz",
"integrity": "sha512-VHMUvOLc6qEd1kTZjc8BMozxgdgs4MP0jxgDW8wur0Hio7EkwrZ0aPeUxbR6FeGqdw+ZB5AXCu24LagnKfaLtQ==",
"dev": true,
"engines": {
"node": ">=16",
@ -975,9 +640,9 @@
}
},
"node_modules/@wikimedia/codex-icons": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.6.1.tgz",
"integrity": "sha512-rtH7dr9JQrsPT5mOwB5Ges06vPUj9+rcGsdQYOo2v4Rj83ot4/RvV3yskjGOghJfBg20T/SqSuW5k9UcnBKONw==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.7.0.tgz",
"integrity": "sha512-g4O8wFAP3Nlm24BHPt4UUaaKYUxzRRMYTXbGfKQ+Ij410H69o7VF+3Q4UJaapY1xXADeT4ptUDX1P+v9wc5RWQ==",
"dev": true,
"engines": {
"node": ">=16",
@ -3612,34 +3277,6 @@
"algoliasearch": "^4.0.0"
}
},
"@esbuild/android-arm": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
"integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
"dev": true,
"optional": true
},
"@esbuild/android-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
"integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
"dev": true,
"optional": true
},
"@esbuild/android-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
"integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
"dev": true,
"optional": true
},
"@esbuild/darwin-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
"integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
"dev": true,
"optional": true
},
"@esbuild/darwin-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
@ -3647,131 +3284,13 @@
"dev": true,
"optional": true
},
"@esbuild/freebsd-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
"integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
"dev": true,
"optional": true
},
"@esbuild/freebsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
"integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
"dev": true,
"optional": true
},
"@esbuild/linux-arm": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
"integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
"dev": true,
"optional": true
},
"@esbuild/linux-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
"integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
"dev": true,
"optional": true
},
"@esbuild/linux-ia32": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
"integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
"dev": true,
"optional": true
},
"@esbuild/linux-loong64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
"integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
"dev": true,
"optional": true
},
"@esbuild/linux-mips64el": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
"integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
"dev": true,
"optional": true
},
"@esbuild/linux-ppc64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
"integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
"dev": true,
"optional": true
},
"@esbuild/linux-riscv64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
"integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
"dev": true,
"optional": true
},
"@esbuild/linux-s390x": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
"integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
"dev": true,
"optional": true
},
"@esbuild/linux-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
"integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
"dev": true,
"optional": true
},
"@esbuild/netbsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
"integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
"dev": true,
"optional": true
},
"@esbuild/openbsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
"integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
"dev": true,
"optional": true
},
"@esbuild/sunos-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
"integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
"dev": true,
"optional": true
},
"@esbuild/win32-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
"integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
"dev": true,
"optional": true
},
"@esbuild/win32-ia32": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
"integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
"dev": true,
"optional": true
},
"@esbuild/win32-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
"integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
"dev": true,
"optional": true
},
"@tootallnate/once": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
"integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
"dev": true
},
"@types/chai": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz",
@ -4055,22 +3574,22 @@
}
},
"@wikimedia/codex": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.6.1.tgz",
"integrity": "sha512-WHc1+DfNSBuX0DNl0AxelbGQ5c8+9NQ9KbTLHLsrvPP1Fo06cOifsWjo8/0hRxfvwV7/uM9y1qeZ/2yyMdkw+A==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@wikimedia/codex/-/codex-0.7.0.tgz",
"integrity": "sha512-SEm9HkuAdfoTrC/tNcftiZU3ljSthYZRdgdFRENSsrgZjVtTeZ5Zr0MPxbTRaEBoeyOk8v1IY3VbgcSAgBdslQ==",
"dev": true,
"requires": {}
},
"@wikimedia/codex-design-tokens": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-design-tokens/-/codex-design-tokens-0.6.1.tgz",
"integrity": "sha512-mCkidhmkJ1iTDkK+Jwm3lShdI3ha6Zj8bvvof7Oc5//WMYShZ/YYJj6ryd0zdy0XOlNPf7PvKgSTiyaYuRduRQ==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-design-tokens/-/codex-design-tokens-0.7.0.tgz",
"integrity": "sha512-VHMUvOLc6qEd1kTZjc8BMozxgdgs4MP0jxgDW8wur0Hio7EkwrZ0aPeUxbR6FeGqdw+ZB5AXCu24LagnKfaLtQ==",
"dev": true
},
"@wikimedia/codex-icons": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.6.1.tgz",
"integrity": "sha512-rtH7dr9JQrsPT5mOwB5Ges06vPUj9+rcGsdQYOo2v4Rj83ot4/RvV3yskjGOghJfBg20T/SqSuW5k9UcnBKONw==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@wikimedia/codex-icons/-/codex-icons-0.7.0.tgz",
"integrity": "sha512-g4O8wFAP3Nlm24BHPt4UUaaKYUxzRRMYTXbGfKQ+Ij410H69o7VF+3Q4UJaapY1xXADeT4ptUDX1P+v9wc5RWQ==",
"dev": true
},
"abab": {

查看文件

@ -13,10 +13,10 @@
"devDependencies": {
"@vitejs/plugin-vue": "4.0.0",
"@vue/test-utils": "2.3.2",
"@wikimedia/codex": "0.6.1",
"@wikimedia/codex-design-tokens": "0.6.1",
"@wikimedia/codex-icons": "0.6.1",
"jsdom": "21.1.1",
"@wikimedia/codex": "0.7.0",
"@wikimedia/codex-design-tokens": "0.7.0",
"@wikimedia/codex-icons": "0.7.0",
"less": "2.5.3",
"postcss": "8.4.21",
"postcss-prefix-selector": "1.16.0",