docs: Fluid Framework 2.0 (BETA) website update (#19143)
This PR bundles relevant infrastructure and content updates to light up FF 2.0 Beta content on the fluidframework.com. --------- Co-authored-by: Pranshu Kumar <pranshukumar@microsoft.com> Co-authored-by: Boris Feldman <borisf@microsoft.com> Co-authored-by: nmsimons <nick@dreamlarge.com> Co-authored-by: Rick Kirkham <Rick-Kirkham@users.noreply.github.com>
|
@ -138,12 +138,14 @@ module.exports = {
|
|||
"JavaScript",
|
||||
"JSON",
|
||||
"Microsoft",
|
||||
"microsoft.com",
|
||||
"npm",
|
||||
"Routerlicious",
|
||||
"Tinylicious",
|
||||
// Without the following entries, markdownlint incorrectly flags various correct usages of tinylicious.
|
||||
"tinylicious.md",
|
||||
"tinylicious-client",
|
||||
'{{< packageref "tinylicious" >}}',
|
||||
],
|
||||
},
|
||||
"reference-links-images": false, // MD052
|
||||
|
@ -152,5 +154,11 @@ module.exports = {
|
|||
indent: 4,
|
||||
},
|
||||
},
|
||||
globs: ["content/**/*.md", "!content/docs/apis", "!content/docs/api", "!node_modules"],
|
||||
globs: [
|
||||
"content/**/*.md",
|
||||
"!content/_index.md", // Markdown-lint doesn't like our use of Hugo's "highlight" shortcode for code blocks
|
||||
"!content/docs/apis",
|
||||
"!content/docs/api",
|
||||
"!node_modules",
|
||||
],
|
||||
};
|
||||
|
|
|
@ -309,7 +309,7 @@ This shortcode can be found in `layouts/shortcodes/apiref.html`.
|
|||
`Markdown` like the following:
|
||||
|
||||
```markdown
|
||||
The {{< apiref "FluidContainer" "class" >}} class can be used to...
|
||||
The {{< apiref "fluid-static" "FluidContainer" "class" >}} class can be used to...
|
||||
```
|
||||
|
||||
will generate something like:
|
||||
|
|
|
@ -14,12 +14,13 @@
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
|
|
@ -8,5 +8,4 @@ children:
|
|||
- '@fluidframework/azure-client'
|
||||
- '@fluid-experimental/odsp-client'
|
||||
layout: aggPackage
|
||||
draft: true
|
||||
---
|
||||
|
|
|
@ -79,11 +79,12 @@ async function renderApiDocumentation(inputDir, outputDir, uriRootDir, apiVersio
|
|||
includeTopLevelDocumentHeading: false, // This will be added automatically by Hugo
|
||||
createDefaultLayout: layoutContent,
|
||||
skipPackage: (apiPackage) => {
|
||||
// Skip `@fluid-internal` and `@fluid-private` packages
|
||||
const packageName = apiPackage.displayName;
|
||||
const packageScope = PackageName.getScope(packageName);
|
||||
|
||||
return ["@fluid-internal", "@fluid-private"].includes(packageScope);
|
||||
// Skip `@fluid-private` packages
|
||||
// TODO: Also skip `@fluid-internal` packages once we no longer have public, user-facing APIs that reference their contents.
|
||||
return ["@fluid-private"].includes(packageScope);
|
||||
},
|
||||
frontMatter: (apiItem) =>
|
||||
createHugoFrontMatter(apiItem, config, customRenderers, apiVersionNum),
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
.carousel {
|
||||
position: relative;
|
||||
}
|
||||
.carousel ul {
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
scroll-snap-type: x mandatory;
|
||||
scroll-snap-points-y: repeat(100%);
|
||||
scroll-behavior: smooth;
|
||||
background: gray;
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.carousel ul::-webkit-scrollbar {
|
||||
display: none; /* Hide scrollbar for Chrome, Safari and Opera */
|
||||
}
|
||||
.carousel ul li {
|
||||
position: relative;
|
||||
min-width: 100%;
|
||||
list-style: none;
|
||||
background: url() center center / cover no-repeat;
|
||||
scroll-snap-align: start;
|
||||
}
|
||||
.carousel ul li > * {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.carousel ul li > img {
|
||||
object-fit: cover;
|
||||
}
|
||||
.carousel ul li > div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
.carousel ol {
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 9;
|
||||
}
|
||||
.carousel ol li {
|
||||
list-style: none;
|
||||
padding: 0 5px;
|
||||
}
|
||||
.carousel ol li a {
|
||||
display: block;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
border: 2px solid white;
|
||||
background: transparent;
|
||||
border-radius: 100%;
|
||||
}
|
||||
.carousel ol li.selected a {
|
||||
background: white;
|
||||
}
|
||||
.carousel .prev,
|
||||
.carousel .next {
|
||||
display: none;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
font-size: 50px;
|
||||
color: white;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
padding: 15px 15px 30px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 9;
|
||||
line-height: 0;
|
||||
}
|
||||
.carousel .next {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
|
@ -13,6 +13,12 @@ footer {
|
|||
background-color: #404049;
|
||||
}
|
||||
|
||||
.availableServices {
|
||||
font-size: 2rem;
|
||||
text-align: center;
|
||||
background-color: #f3f5f7;
|
||||
}
|
||||
|
||||
.row-cta {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
@ -24,10 +30,9 @@ footer {
|
|||
}
|
||||
|
||||
.cta {
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
width: fit-content;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
display: inline-block;
|
||||
flex-flow: column;
|
||||
color: #f3f5f7;
|
||||
transition: 0.1s ease-in;
|
||||
|
|
|
@ -51,7 +51,7 @@ permalinks:
|
|||
params:
|
||||
appInsightKey: "" # This is provided by the build system as an env variable
|
||||
cookies: false
|
||||
customCSS: ["css/fluid.css", "css/tango.css"]
|
||||
customCSS: ["css/fluid.css", "css/tango.css", "css/carousel.css"]
|
||||
dateform: "Jan 2, 2006"
|
||||
dateformNum: "2006-01-02"
|
||||
dateformNumTime: "2006-01-02 15:04 -0700"
|
||||
|
@ -59,12 +59,12 @@ params:
|
|||
githubRepo: "microsoft/FluidFramework"
|
||||
twitterHandle: "fluidframework"
|
||||
banner:
|
||||
showBanner: true # show or hide the banner completely
|
||||
showBanner: false # show or hide the banner completely
|
||||
bannerClose: false # show or hide the close button on the banner
|
||||
version: "0.50"
|
||||
urlRef: "docs/updates/v0.50.md"
|
||||
message: | # if set, this will override the release notes updates
|
||||
[Azure Fluid Relay](/docs/deployment/azure-frs/) is now generally available! [Learn more.](https://devblogs.microsoft.com/microsoft365dev/announcing-general-availability-of-azure-fluid-relay-service/)
|
||||
Fluid Framework 2.0 beta is available now! [Learn more.](/blogs/)
|
||||
|
||||
menu:
|
||||
main:
|
||||
|
@ -80,9 +80,6 @@ menu:
|
|||
- name: "Community"
|
||||
url: "/community/"
|
||||
weight: -60
|
||||
# - name: "Updates"
|
||||
# url: "/posts/"
|
||||
# weight: -50
|
||||
|
||||
old_section:
|
||||
- identifier: "quick-start"
|
||||
|
|
|
@ -1,34 +1,297 @@
|
|||
---
|
||||
title: "Fluid Framework"
|
||||
title: "Fluid Framework: Build performant real-time collaboration with ease"
|
||||
aliases:
|
||||
- /playground/
|
||||
summary: "An open-source client technology stack that enables real-time collaboration, provides developers with easy-to-understand data structures automatically keeps in sync between clients"
|
||||
---
|
||||
|
||||
{{< jumbotron
|
||||
lead=`Data Sync <strong>Reimagined</strong>`
|
||||
subText="Real time. Web first. Open source."
|
||||
>}}
|
||||
<div class="jumbotron text-center">
|
||||
<h1 class="display-4"><strong>Real-time. Multiuser. Collaboration.</strong></h1>
|
||||
<p class="lead">Empower collaborative innovation with Fluid Framework's seamless, high-performance tech stack for real-time applications.</p>
|
||||
<p><iframe width="560" height="315" src="https://www.youtube.com/embed/1okQVFqlMxU?si=BlpSaIHaWY47_OFe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe></p>
|
||||
<p><a class="cta link-button get-started" style="background-color: #0066b8 !important; text-decoration: none;" href="/docs/start/quick-start/">Get started with Fluid Framework today!</a></p>
|
||||
</div>
|
||||
|
||||
{{< cta_container >}}
|
||||
{{< cta
|
||||
linkClasses="get-started"
|
||||
linkURL="/docs/start/quick-start/"
|
||||
iconClasses="get-started"
|
||||
linkText="Get Started"
|
||||
>}}
|
||||
<div class="value-props">
|
||||
<h2><strong>Start building with Fluid Framework</strong></h2><br/>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<a class="value-prop" id="home-value-prop-easy-to-use-link" href="#easy-to-use">
|
||||
<div class="value-prop-icon easy-to-use"></div>
|
||||
<b>Easy to use</b>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<a class="value-prop" id="home-value-prop-open-source-link" href="#open-source">
|
||||
<div class="value-prop-icon open-source"></div>
|
||||
<b>Open source</b>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-sm-4 col-xs-6">
|
||||
<a class="value-prop" id="home-value-prop-open-source-link" href="#perf">
|
||||
<div class="value-prop-icon better-perf"></div>
|
||||
<b>Industry-leading</br>speed & performance</b>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{< cta
|
||||
linkClasses="learn-more"
|
||||
linkURL="/docs/"
|
||||
iconClasses="learn-more"
|
||||
linkText="Learn More"
|
||||
>}}
|
||||
{{<swimlane_container fullPage="yes">}}
|
||||
<div class="swimlane customers">
|
||||
<div class="row text-center">
|
||||
<h2><strong>Who's using Fluid Framework</strong></h2>
|
||||
</div>
|
||||
<div class="row customers-list text-center">
|
||||
<div class="col-xs-6 col-sm-3 col-md-2">
|
||||
<div class="row">
|
||||
<img height="50" width="50" alt="Autodesk" src="images/Autodesk_logo.png">
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Autodesk</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-sm-3 col-md-2">
|
||||
<div class="row">
|
||||
<img height="50" width="50" alt="Hexagon" src="images/Hexagon_logo.png">
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Hexagon</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-sm-3 col-md-2">
|
||||
<div class="row">
|
||||
<svg width="50" height="50"><image xlink:href="images/Loop_logo.svg" width="50" height="50"></svg>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Microsoft Loop</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-sm-3 col-md-2">
|
||||
<div class="row">
|
||||
<svg width="50" height="50"><image xlink:href="images/Teams_logo.svg" width="50" height="50"></svg>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Microsoft Teams</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-sm-3 col-md-2">
|
||||
<div class="row">
|
||||
<img height="50" width="50" alt="PowerApps" src="images/PowerApps_logo.png">
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Power Apps</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-sm-3 col-md-2">
|
||||
<div class="row">
|
||||
<img height="50" width="50" alt="Whiteboard" src="images/Whiteboard_logo.png">
|
||||
</div>
|
||||
<div class="row">
|
||||
<h3>Whiteboard</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{< cta
|
||||
linkClasses="play"
|
||||
linkURL="/docs/start/examples/"
|
||||
iconClasses="play"
|
||||
linkText="Examples"
|
||||
>}}
|
||||
{{< /cta_container >}}
|
||||
{{</swimlane_container>}}
|
||||
|
||||
{{<swimlane_container fullPage="yes">}}
|
||||
{{<swimlane
|
||||
id="easy-to-use"
|
||||
title="Easy to use"
|
||||
subTitle="Transform your collaborative experience with our developer friendly framework - where simplicity meets powerful functionality effortlessly. The framework provides usability that drives innovation within Microsoft and across the industry by dramatically lowering the difficulty and cost of building innovative, collaborative software."
|
||||
img="/images/E1C1.svg"
|
||||
imgAlt="easy to use image"
|
||||
>}}
|
||||
{{<swimlane
|
||||
id="open-source"
|
||||
title="Open source"
|
||||
subTitle="We believe that an <strong>open, inclusive, and respectful </strong>community will help shape a better future for this project. That's why Fluid Framework is made available for <strong>FREE</strong> as an <strong>Open Source project</strong> under the MIT license."
|
||||
img="/images/1F513.svg"
|
||||
imgAlt="github logo"
|
||||
pos="right"
|
||||
>}}
|
||||
{{<swimlane
|
||||
id="perf"
|
||||
title="Industry-leading speed & performance"
|
||||
subTitle="Unleash unparalleled speed and performance with our cutting-edge solution for building real-time collaborative applications. Collaborative features are only successful if they are fast, scale to large data and user bases. Fluid offers an approachable programming model that leverages mainstream web technology while delivering best-in-class performance."
|
||||
img="/images/1F680.svg"
|
||||
imgAlt="speed and performance image"
|
||||
>}}
|
||||
{{</swimlane_container>}}
|
||||
|
||||
{{<swimlane_container fullPage="no">}}
|
||||
<div class="swimlane samplecode">
|
||||
<div class="row title">
|
||||
<div class="text-center">
|
||||
<h2><strong>See How It Works</strong></h2>
|
||||
</div>
|
||||
<div class="col-md-8 text-center">
|
||||
<h3>Sample Code</h3>
|
||||
</div>
|
||||
<div class="col-md-4 text-center">
|
||||
<h3>Sample Output</h3>
|
||||
</div>
|
||||
<div class="col-md-8" style="text-left; height:650px; overflow-x: auto; padding-left: 50px;">
|
||||
<code>
|
||||
{{< highlight typescript >}}
|
||||
import { SharedTree, TreeConfiguration, SchemaFactory, Tree } from "fluid-framework";
|
||||
import { TinyliciousClient } from "@fluidframework/tinylicious-client";
|
||||
|
||||
const client = new TinyliciousClient();
|
||||
const containerSchema = {
|
||||
initialObjects: { diceTree: SharedTree },
|
||||
};
|
||||
|
||||
const root = document.getElementById("content");
|
||||
|
||||
// The string passed to the SchemaFactory should be unique
|
||||
const sf = new SchemaFactory("fluidHelloWorldSample");
|
||||
|
||||
// Here we define an object we'll use in the schema, a Dice.
|
||||
class Dice extends sf.object("Dice", {
|
||||
value: sf.number,
|
||||
}) {}
|
||||
|
||||
// Here we define the tree schema, which has a single Dice object starting at 1.
|
||||
// We'll call schematize() on the SharedTree using this schema, which will give us a tree view to work with.
|
||||
const treeConfiguration = new TreeConfiguration(
|
||||
Dice,
|
||||
() =>
|
||||
new Dice({
|
||||
value: 1,
|
||||
}),
|
||||
);
|
||||
|
||||
const createNewDice = async () => {
|
||||
const { container } = await client.createContainer(containerSchema);
|
||||
const dice = container.initialObjects.diceTree.schematize(treeConfiguration).root;
|
||||
const id = await container.attach();
|
||||
renderDiceRoller(dice, root);
|
||||
return id;
|
||||
};
|
||||
|
||||
const loadExistingDice = async (id) => {
|
||||
const { container } = await client.getContainer(id, containerSchema);
|
||||
const dice = container.initialObjects.diceTree.schematize(treeConfiguration).root;
|
||||
renderDiceRoller(dice, root);
|
||||
};
|
||||
|
||||
async function start() {
|
||||
if (location.hash) {
|
||||
await loadExistingDice(location.hash.substring(1));
|
||||
} else {
|
||||
const id = await createNewDice();
|
||||
location.hash = id;
|
||||
}
|
||||
}
|
||||
|
||||
start().catch((error) => console.error(error));
|
||||
|
||||
// Define the view
|
||||
const template = document.createElement("template");
|
||||
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
.wrapper { text-align: center }
|
||||
.dice { font-size: 200px }
|
||||
.roll { font-size: 50px;}
|
||||
</style>
|
||||
<div class="wrapper">
|
||||
<div class="dice"></div>
|
||||
<button class="roll"> Roll </button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const renderDiceRoller = (dice, elem) => {
|
||||
elem.appendChild(template.content.cloneNode(true));
|
||||
|
||||
const rollButton = elem.querySelector(".roll");
|
||||
const diceElem = elem.querySelector(".dice");
|
||||
|
||||
// Set the value at our dataKey with a random number between 1 and 6.
|
||||
rollButton.onclick = () => {
|
||||
dice.value = Math.floor(Math.random() * 6) + 1;
|
||||
};
|
||||
|
||||
// Get the current value of the shared data to update the view whenever it changes.
|
||||
const updateDice = () => {
|
||||
const diceValue = dice.value;
|
||||
// Unicode 0x2680-0x2685 are the sides of a dice (⚀⚁⚂⚃⚄⚅)
|
||||
diceElem.textContent = String.fromCodePoint(0x267f + diceValue);
|
||||
diceElem.style.color = `hsl(${diceValue * 60}, 70%, 30%)`;
|
||||
};
|
||||
updateDice();
|
||||
|
||||
// Use the changed event to trigger the rerender whenever the value changes.
|
||||
Tree.on(dice, "afterChange", updateDice);
|
||||
// Setting "fluidStarted" is just for our test automation
|
||||
window["fluidStarted"] = true;
|
||||
};
|
||||
{{< / highlight >}}
|
||||
</code>
|
||||
</div>
|
||||
<div class="col-md-4 text-center" style="padding-right: 50px;">
|
||||
{{< fluid_bundle_loader idPrefix="dice-roller"
|
||||
bundleName="dice-roller.2021-09-24.js" >}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<p><br/><a class="cta link-button btn-info get-started" style="background-color: #17a2b8 !important; text-decoration: none;" href="/docs/start/examples/"><small>Try the other samples</small></a><br/><br/></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{</swimlane_container>}}
|
||||
|
||||
{{<swimlane_container fullPage="yes">}}
|
||||
<div class="swimlane availableServices">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="row title" style="text-align: center;">
|
||||
<h2><strong>Fluid Framework in the Cloud</strong></h2>
|
||||
</div>
|
||||
<div class="row diagram text-center">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<img height="450" width="850" alt="Architecture" src="images/FF Stack.png"><br/><br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row availableServices-list">
|
||||
<div class="availableServices">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<svg width="50" height="50"><image xlink:href="images/azure.svg" width="50" height="50"></svg><br/>
|
||||
<h2>Azure Fluid Relay</h2>
|
||||
</div>
|
||||
<div>
|
||||
<p>Azure Fluid Relay is a cloud service that enables real-time collaboration on shared data models. It is a fully managed service that provides a secure, scalable, and reliable way to connect clients to each other and to the data models they share.</p>
|
||||
</div>
|
||||
<div>
|
||||
<a class="cta link-button btn-info get-started" style="background-color: #17a2b8 !important; text-decoration: none;" href="https://azure.microsoft.com/en-us/products/fluid-relay/#overview"><small>Learn more about Azure Fluid Relay</small></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<svg width="50" height="50"><image xlink:href="images/SharePoint_64x.svg" width="50" height="50"></svg><br/>
|
||||
<h2>SharePoint Embedded</h2>
|
||||
</div>
|
||||
<div>
|
||||
<p>Microsoft SharePoint Embedded is a cloud-based file and document management system suitable for use in any application. It is a new API-only solution which enables app developers to harness the power of the Microsoft 365 file and document storage platform for any app, and is suitable for enterprises building line of business applications and ISVs building multi-tenant applications.</p>
|
||||
</div>
|
||||
<div>
|
||||
<a class="cta link-button btn-info get-started" style="background-color: #17a2b8 !important; text-decoration: none;" href="https://learn.microsoft.com/en-us/sharepoint/dev/embedded/overview"><small>Learn more about SharePoint Embedded</small></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{</swimlane_container>}}
|
||||
|
|
|
@ -33,8 +33,7 @@ Narrative documentation
|
|||
: The overall structure of the documentation comes from Markdown files in the `docs/` folder.
|
||||
|
||||
Automated API documentation
|
||||
: The contents of the [API]({{< relref "/docs/apis/_index.md" >}}) section is built from [TSDoc
|
||||
comments](https://api-extractor.com/pages/tsdoc/doc_comment_syntax/) in the source code.
|
||||
: The contents of the `docs/api` section is built from [TSDoc comments](https://api-extractor.com/pages/tsdoc/doc_comment_syntax/) in the source code.
|
||||
|
||||
## Features
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ editor: tylerbutler
|
|||
|
||||
The audience is the collection of users connected to a container. When your app creates a container using a service-specific client library, the app is provided with a service-specific audience object for that container as well. Your code can query the audience object for connected users and use that information to build rich and collaborative user presence features.
|
||||
|
||||
This document will explain how to use the audience APIs and then provide examples on how to use the audience to show user presence. For anything service-specific, the [Tinylicious]({{< relref "tinylicious.md" >}}) Fluid service is used.
|
||||
This document will explain how to use the audience APIs and then provide examples on how to use the audience to show user presence. For anything service-specific, the [Tinylicious]({{< relref "/docs/testing/tinylicious.md" >}}) Fluid service is used.
|
||||
|
||||
## Working with the audience
|
||||
|
||||
|
@ -131,15 +131,16 @@ In some cases, the user data could be generated locally or fetched from an exter
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ But the new container has a different ID from the deleted one and subsequent cli
|
|||
|
||||
#### Handling publication status
|
||||
|
||||
Your code can test for the publication status with the [container.AttachState]({{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md#attachstate-property" >}}) property which has an [AttachState]({{< relref "/docs/apis/container-definitions.md#attachstate-enum" >}}) value.
|
||||
Your code can test for the publication status with the [container.AttachState]({{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}#attachstate-property) property which has an [AttachState]({{< packageref "container-definitions" "v2" >}}#attachstate-enum) value.
|
||||
This can be useful if your application will publish the container in some code paths on the creating client, but not others.
|
||||
For example, on the creating computer, you don't want to call `container.attach` if it has already been called. In simple cases, you can know at coding time if that has happened, but when the creating client in complex code flows and calls of `container.attach` appear in more than one branch, you may need to test for this possibility. The following is a simple example.
|
||||
|
||||
|
@ -254,7 +254,7 @@ The container transitions to this state automatically when it is fully caught up
|
|||
|
||||
There are scenarios in which you need to control the connection status of the container. To assist, the `container` object has the following APIs:
|
||||
|
||||
- A [container.connectionState]({{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md#connectionstate-propertysignature" >}}) property of type `ConnectionState`. There are four possible values for the property:
|
||||
- A [container.connectionState]({{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}#connectionstate-propertysignature) property of type `ConnectionState`. There are four possible values for the property:
|
||||
|
||||
- `Disconnected`
|
||||
- `EstablishingConnection`: Your code should treat this state the same as it treats the disconnected state. See [Examples](#examples).
|
||||
|
@ -343,4 +343,4 @@ But it would be possible for your code to create a new local container object fo
|
|||
2. Open the Visio file and change it as needed.
|
||||
3. "Save as" the Visio file but select SVG as the file type.
|
||||
4. Ensure that the destination folder is the ./images subfolder and complete the "Save As" process.
|
||||
-->
|
||||
-->
|
||||
|
|
|
@ -8,7 +8,7 @@ editor: tylerbutler
|
|||
The container is the primary unit of encapsulation in the Fluid Framework.
|
||||
It enables a group of clients to access the same set of shared objects and co-author changes on those objects.
|
||||
It is also a permission boundary ensuring visibility and access only to permitted clients.
|
||||
A container is represented by the [FluidContainer]({{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}) type and consists of a collection of shared objects and APIs to manage the life cycle of those objects.
|
||||
A container is represented by the [FluidContainer]({{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}) type and consists of a collection of shared objects and APIs to manage the life cycle of those objects.
|
||||
|
||||
This article explains:
|
||||
|
||||
|
@ -31,7 +31,7 @@ The device is a subsequent client in all future sessions.
|
|||
|
||||
Your code creates containers using APIs provided by a service-specific client library.
|
||||
Each service-specific client library implements a common API for manipulating containers.
|
||||
For example, the [Tinylicious library]({{< relref "Tinylicious" >}}) provides [these APIs]({{< relref "docs/apis/tinylicious-client.md" >}}) for the Tinylicious Fluid service.
|
||||
For example, the [Tinylicious library]({{< relref "/docs/testing/tinylicious.md" >}}) provides [these APIs]({{< relref "docs/api/v1/tinylicious-client.md" >}}) for the Tinylicious Fluid service.
|
||||
These common APIs enable your code to specify what shared objects should live in the `FluidContainer`, and to connect to the container once it is created.
|
||||
|
||||
### Container schema
|
||||
|
@ -215,15 +215,16 @@ An example of a container service is the [Audience]({{< relref "audience.md" >}}
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -165,15 +165,16 @@ An example where this is useful is building a collaborative storyboarding applic
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ There are a number of shared objects built into the Fluid Framework. See [Distri
|
|||
|
||||
DDSes automatically ensure that each client has access to the same state. They're called *distributed data structures*
|
||||
because they are similar to data structures used commonly when programming, like strings, maps/dictionaries, and
|
||||
sequences/lists. The APIs provided by DDSes are designed to be familiar to programmers who've used these types of data
|
||||
objects, and arrays. The APIs provided by DDSes are designed to be familiar to programmers who've used these types of data
|
||||
structures before. For example, the [SharedMap][] DDS is used to store key/value pairs, like a typical map or dictionary
|
||||
data structure, and provides `get` and `set` methods to store and retrieve data in the map.
|
||||
|
||||
|
@ -27,8 +27,7 @@ However, a DDS is not *just* a local object. A DDS can also be changed by other
|
|||
|
||||
{{% callout tip %}}
|
||||
|
||||
Most distributed data structures are prefixed with "Shared" by convention. *SharedMap*, *SharedMatrix*, *SharedString*,
|
||||
etc. This prefix indicates that the object is shared between multiple clients.
|
||||
Most distributed data structures are prefixed with "Shared" by convention. *SharedMap*, *SharedTree*, etc. This prefix indicates that the object is shared between multiple clients.
|
||||
|
||||
{{% /callout %}}
|
||||
|
||||
|
@ -69,7 +68,7 @@ The potential down-side to this approach is consistency; if another collaborator
|
|||
|
||||
The DDSes will apply remote operations as they are made, and will always arrive at a consistent state.
|
||||
|
||||
Many of the most commonly used DDSes are optimistic, including [SharedMap][] and [SharedString][].
|
||||
Many of the most commonly used DDSes are optimistic, including [SharedMap][], [SharedString][], and in Fluid Framework 2.0 and later [SharedTree][].
|
||||
|
||||
### Consensus-based data structures
|
||||
|
||||
|
@ -115,6 +114,12 @@ see [Fluid handles]({{< relref "handles.md" >}}).
|
|||
|
||||
[handles-example]: {{< relref "data-modeling.md#using-handles-to-store-and-retrieve-shared-objects" >}}
|
||||
|
||||
{{< callout note >}}
|
||||
|
||||
If you are considering storing a DDS within another DDS in order to give your app's data a hierarchical structure, consider using a [SharedTree][] DDS instead.
|
||||
|
||||
{{</callout >}}
|
||||
|
||||
## Events
|
||||
|
||||
When a distributed data structure is changed by the Fluid runtime, it raises events. Your app can listen to these events so
|
||||
|
@ -127,8 +132,6 @@ myMap.on("valueChanged", () => {
|
|||
});
|
||||
```
|
||||
|
||||
Refer to later sections for more details about the events raised by each DDS.
|
||||
|
||||
## Picking the right data structure
|
||||
|
||||
Because distributed data structures can be stored within each other, you can combine DDSes to create collaborative data
|
||||
|
@ -179,23 +182,38 @@ This results in someone's changes being "lost" from a user's perspective. This m
|
|||
However, if your scenario requires users to edit individual properties of the shape, then the SharedMap LWW merge
|
||||
strategy probably won't give you the behavior you want.
|
||||
|
||||
However, you could address this problem by storing individual shape properties in `SharedMap` keys. Instead of storing a
|
||||
However, you could address this problem in different ways depending on which version of Fluid Framework you are using.
|
||||
|
||||
In version 1.0, store individual shape properties in `SharedMap` keys. Instead of storing a
|
||||
JSON object with all the data, your code can break it apart and store the length in one `SharedMap` key, the width in another,
|
||||
etc. With this data model, users can change individual properties of the shape without overwriting other users' changes.
|
||||
|
||||
You likely have more than one shape in your data model, so you could create a `SharedMap` object to store all the shapes, then
|
||||
store the `SharedMaps` representing each shape within that parent `SharedMap` object.
|
||||
|
||||
In version 2.0, there's a better, way. Store a shape as an object node of a `SharedTree`. Your code can store the length in one property of the object node, the width in another, etc. Again, users can change individual properties of the shape without overwriting other users' changes.
|
||||
|
||||
When you have more than one shape in your data model, you could create a *array* node in the `SharedTree`, with child object nodes to store all the shapes.
|
||||
|
||||
### Key-value data
|
||||
|
||||
These DDSes are used for storing key-value data. They are all optimistic and use a last-writer-wins merge policy.
|
||||
|
||||
* [SharedMap][] -- a basic key-value distributed data structure.
|
||||
* Map nodes in a [SharedTree][] -- a hierarchical data structure with three kinds of complex nodes; maps (similar to [SharedMap][]), arrays, and JavaScript objects. There are also several kinds of leaf nodes, including boolean, string, number, null, and [Fluid handles]({{< relref "handles.md" >}}).
|
||||
|
||||
### Array-like data
|
||||
|
||||
* Array nodes in a [SharedTree][] -- a hierarchical data structure with three kinds of complex nodes; maps (similar to [SharedMap][]), arrays, and JavaScript objects. There are also several kinds of leaf nodes, including boolean, string, number, null, and [Fluid handles]({{< relref "handles.md" >}}).
|
||||
|
||||
### Object data
|
||||
|
||||
* Object nodes in a [SharedTree][] -- a hierarchical data structure with three kinds of complex nodes; maps (similar to [SharedMap][]), arrays, and JavaScript objects. There are also several kinds of leaf nodes, including boolean, string, number, null, and [Fluid handles]({{< relref "handles.md" >}}).
|
||||
|
||||
### Specialized data structures
|
||||
|
||||
* [SharedCounter][] -- a distributed counter.
|
||||
* [SharedString][] -- a specialized data structure for handling collaborative text.
|
||||
* [SharedCounter][] -- a distributed counter. (Deprecated in Fluid Framework 2.0.)
|
||||
* [SharedString][] -- a specialized data structure for handling collaborative text. (Deprecated in Fluid Framework 2.0.)
|
||||
|
||||
<!-- AUTO-GENERATED-CONTENT:START (INCLUDE:path=../../../_includes/links.md) -->
|
||||
|
||||
|
@ -218,15 +236,16 @@ These DDSes are used for storing key-value data. They are all optimistic and use
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ When a [container]({{< relref "containers.md" >}}) is loaded, there will be seve
|
|||
|
||||
The following is an example of how to enable experimental features with `AzureClient`.
|
||||
|
||||
1. First, implement [IConfigProviderBase]({{< relref "/docs/apis/core-interfaces/iconfigproviderbase-interface" >}}). For example:
|
||||
1. First, implement [IConfigProviderBase]({{< apiref "core-interfaces" "IConfigProviderBase" "interface" "v2" >}}). For example:
|
||||
|
||||
```typescript
|
||||
const configProvider = (settings: Record<string, ConfigTypes>): IConfigProviderBase => ({
|
||||
|
|
|
@ -23,7 +23,7 @@ Fluid clients require a centralized service that all connected clients use to se
|
|||
|
||||
Each service-specific library adheres to a common API structure and has the primary goal of creating and retrieving container objects. The common structure enables you to switch from one service to another with minimal code changes. There are two services currently available:
|
||||
|
||||
- The [Tinylicious service]({{< relref "Tinylicious" >}}) runs on your development computer and is used for development and testing. It is used in Fluid examples throughout this documentation.
|
||||
- The [Tinylicious service]({{< relref "/docs/testing/tinylicious.md" >}}) runs on your development computer and is used for development and testing. It is used in Fluid examples throughout this documentation.
|
||||
- [Azure Fluid Relay]({{< relref "azure-frs.md" >}}) runs in Azure and enables high-scale production scenarios.
|
||||
|
||||
See [Service-specific client libraries](#service-specific-client-libraries) for more details.
|
||||
|
@ -63,7 +63,7 @@ Fluid works with multiple service implementations. Each service has a correspond
|
|||
|
||||
For specifics about each service-specific client implementation see their corresponding documentation.
|
||||
|
||||
- The client library for the [Tinylicious]({{< relref "Tinylicious" >}}) service is in the package [@fluidframework/tinylicious-client](https://www.npmjs.com/package/@fluidframework/tinylicious-client).
|
||||
- The client library for the [Tinylicious]({{< relref "/docs/testing/tinylicious.md" >}}) service is in the package [@fluidframework/tinylicious-client](https://www.npmjs.com/package/@fluidframework/tinylicious-client).
|
||||
- The client library for the [Azure Fluid Relay]({{< relref "azure-frs.md" >}}) is in the package [@fluidframework/azure-client](https://www.npmjs.com/package/@fluidframework/azure-client).
|
||||
|
||||
For more information see [Packages]({{< relref "packages.md" >}}).
|
||||
|
@ -89,15 +89,16 @@ For more information see [Packages]({{< relref "packages.md" >}}).
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ You'll use one or more shared objects in your container to model your collaborat
|
|||
three data structures that cover a broad range of scenarios:
|
||||
|
||||
1. [SharedMap]({{< relref "/docs/data-structures/map.md" >}}), a map-like data structure for storing key/value pair data.
|
||||
2. [SharedDirectory]({{< relref "shareddirectory-class.md" >}}), a map-like data structure with ability to organize keys into subdirectories.
|
||||
3. [SharedString]({{< relref "string.md" >}}), a data structure for string data.
|
||||
2. [SharedString]({{< relref "/docs/data-structures/string.md" >}}), a data structure for string data.
|
||||
|
||||
## Package scopes
|
||||
|
||||
|
@ -38,7 +37,7 @@ Fluid Framework packages are published under one of the following npm scopes:
|
|||
- @fluid-internal
|
||||
- @fluid-tools
|
||||
|
||||
In addition to the scoped packages, two unscoped packages are published: the [fluid-framework[] package, described earlier, and the `tinylicious` package, which contains a minimal Fluid server. For more information, see [Tinylicious]({{< relref "tinylicious.md" >}}).
|
||||
In addition to the scoped packages, two unscoped packages are published: the [fluid-framework[] package, described earlier, and the `tinylicious` package, which contains a minimal Fluid server. For more information, see [Tinylicious]({{< relref "/docs/testing/tinylicious.md" >}}).
|
||||
|
||||
Unless you are contributing to the Fluid Framework, you should only need the unscoped packages and packages from the **@fluidframework** scope.
|
||||
You can [read more about the scopes and their intent][scopes] in the Fluid Framework wiki.
|
||||
|
@ -66,15 +65,16 @@ You can [read more about the scopes and their intent][scopes] in the Fluid Frame
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -95,15 +95,16 @@ console.log(text === text2) // true
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -147,15 +147,16 @@ The payload sent back in response to the `connectRequest` should include all the
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -96,15 +96,16 @@ Data Objects' data structures will be summarized.
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -3,6 +3,12 @@ title: SharedCounter
|
|||
menuPosition: 5
|
||||
---
|
||||
|
||||
{{< callout note >}}
|
||||
|
||||
The `SharedCounter` DDS is deprecated in Fluid Framework 2.0.
|
||||
|
||||
{{< /callout >}}
|
||||
|
||||
<!-- IMPORTANT: Don't manually edit the auto-generated content below. Instead, edit the source file (look at the path
|
||||
argument) and then run "npm run build:md-magic" from the docs folder. That will update all autogenerated
|
||||
content, so you should commit the resulting changes. -->
|
||||
|
@ -157,8 +163,8 @@ Since `updateCounterValueLabel` is listening for all `incremented` events, the v
|
|||
For a comprehensive view of the `counter` package's API documentation, see [the SharedCounter API docs]({{< ref "docs/api/v1/counter.md" >}}).
|
||||
|
||||
<!-- Links -->
|
||||
[increment]: {{< relref "isharedcounter-interface.md#increment-methodsignature" >}}
|
||||
[incremented]: {{< relref "isharedcounterevents-interface.md#_call_-callsignature" >}}
|
||||
[increment]: {{< apiref "counter" "ISharedCounter" "interface" "v1" >}}#increment-methodsignature
|
||||
[incremented]: {{< apiref "counter" "ISharedCounterEvents" "interface" "v1" >}}#_call_-callsignature"
|
||||
[Optimistic DDS]: {{< relref "dds.md#optimistic-data-structures" >}}
|
||||
[SharedMap]: {{< relref "map.md" >}}
|
||||
[SharedMap creation]: {{< relref "map.md#creation" >}}
|
||||
|
|
|
@ -45,6 +45,7 @@ These DDSes are used for storing key-value data. They are optimistic and use a l
|
|||
the value of a pair can be a complex object, the value of any given pair can only be changed whole-for-whole.
|
||||
|
||||
- [SharedMap][] -- a basic key-value data structure.
|
||||
- Map nodes in a [SharedTree][] -- a hierarchical data structure with three kinds of complex nodes; maps (similar to [SharedMap][]), arrays, and JavaScript objects. There are also several kinds of leaf nodes, including boolean, string, number, null, and [Fluid handles]({{< relref "handles.md" >}}).
|
||||
|
||||
### Key Value Scenarios
|
||||
|
||||
|
@ -56,9 +57,8 @@ Key-value data structures are the most common choice for many scenarios.
|
|||
|
||||
### Common issues and best practices for key-value DDSes
|
||||
|
||||
- Storing a counter in a map will have unexpected behavior. Use the [SharedCounter][] instead.
|
||||
- Storing arrays, lists, or logs in a key-value entry may lead to unexpected behavior because users can't
|
||||
collaboratively modify parts of one entry. Try storing the array or list data in a SharedSequence or SharedInk.
|
||||
- Storing arrays, lists, or logs in a single key-value entry may lead to unexpected behavior because users can't
|
||||
collaboratively modify parts of one entry. Try storing the data in an array node of a [SharedTree][].
|
||||
- Storing a lot of data in one key-value entry may cause performance or merge issues. Each update will update the entire
|
||||
value rather than merging two updates. Try splitting the data across multiple keys.
|
||||
|
||||
|
@ -74,6 +74,12 @@ Key-value data structures are the most common choice for many scenarios.
|
|||
from the sequence and then insert a new value at the position where the old value was. But because other clients can
|
||||
insert and remove, there's no reliable way of getting the new value into the the desired position.
|
||||
|
||||
## Hierarchical data
|
||||
|
||||
FluidFramework 2.0 preview provides a DDS can be used for hierarchical data structures. It is optimistic and uses a last-writer-wins merge policy.
|
||||
|
||||
- [SharedTree][] -- a tree of data with three kinds of complex nodes; maps (similar to [SharedMap][]), arrays, and JavaScript objects. There are also several kinds of leaf nodes, including boolean, string, number, null, and [Fluid handles]({{< relref "handles.md" >}}).
|
||||
|
||||
## Strings
|
||||
|
||||
The SharedString DDS is used for unstructured text data that can be collaboratively edited. It is optimistic.
|
||||
|
@ -86,7 +92,7 @@ The SharedString DDS is used for unstructured text data that can be collaborativ
|
|||
|
||||
## Specialized data structures
|
||||
|
||||
- [SharedCounter][] -- a counter.
|
||||
- [SharedCounter][] -- a counter. (Deprecated in Fluid Framework 2.0.)
|
||||
- `SharedCounter` is useful to keep track of increments/decrements of integer values.
|
||||
While a key-value data structure appears like a good fit, two clients simultaneously setting the same key can [cause issues]({{< relref "counter.md/#why-a-specialized-dds" >}}).
|
||||
By contrast, clients can increase or decrease the `SharedCounter` value by a specified amount, but they can't set it to a specified value.
|
||||
|
@ -132,15 +138,16 @@ Typical scenarios require the connected clients to "agree" on some course of act
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ aliases:
|
|||
argument) and then run "npm run build:md-magic" from the docs folder. That will update all autogenerated
|
||||
content, so you should commit the resulting changes. -->
|
||||
|
||||
<!-- AUTO-GENERATED-CONTENT:START (INCLUDE:path=../../../../packages/dds/sequence/README.md&start=24&end=514) -->
|
||||
<!-- AUTO-GENERATED-CONTENT:START (INCLUDE:path=../../../../packages/dds/sequence/README.md&start=18&end=509) -->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- NOTE: This section is automatically generated by embedding the referenced file contents. Do not update these generated contents directly. -->
|
||||
|
|
|
@ -59,7 +59,7 @@ efficient spatial querying of the nearest Marker to a given position. -->
|
|||
argument) and then run "npm run build:md-magic" from the docs folder. That will update all autogenerated
|
||||
content, so you should commit the resulting changes. -->
|
||||
|
||||
<!-- AUTO-GENERATED-CONTENT:START (INCLUDE:path=../../../../packages/dds/sequence/README.md&start=590&end=607) -->
|
||||
<!-- AUTO-GENERATED-CONTENT:START (INCLUDE:path=../../../../packages/dds/sequence/README.md&start=584&end=602) -->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- NOTE: This section is automatically generated by embedding the referenced file contents. Do not update these generated contents directly. -->
|
||||
|
@ -107,15 +107,16 @@ efficient spatial querying of the nearest Marker to a given position. -->
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -0,0 +1,556 @@
|
|||
---
|
||||
title: SharedTree
|
||||
menuPosition: 6
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
The `SharedTree` distributed data structure (DDS), available in Fluid Framework 2.0 preview and later, is used to store most or all of your application's shared data in a hierarchical structure.
|
||||
|
||||
A `SharedTree` object has the following characteristics:
|
||||
|
||||
- It has a root and can have several types of branch nodes and several types of leaf nodes.
|
||||
- Although there are some exceptions, for the most part, each type of node closely mirrors a familiar JavaScript datatype, such as object, map, array, boolean, number, string, and null.
|
||||
- Again, with exceptions, your code accesses nodes with the syntax of JavaScript and TypeScript, such as dot notation, property assignment, and array indexes.
|
||||
- Besides being of the type `SharedTree`, the object must also conform to a schema that your code creates so it has an application-specific strong typing too.
|
||||
- The various types of branch nodes can be nested in one another (subject to the constraints of the schema).
|
||||
|
||||
### Node types
|
||||
|
||||
The following leaf node types are available:
|
||||
|
||||
- **boolean**: Works identically to a JavaScript boolean.
|
||||
- **number**: Works identically to a JavaScript JavaScript number.
|
||||
- **string**: Works identically to a JavaScript string.
|
||||
- **null**: Works identically to a JavaScript null.
|
||||
- **FluidHandle**: A handle to a Fluid DDS or Data Object in the current container. For more information about handles see [Handles]({{< relref "handles.md" >}}).
|
||||
|
||||
The following subsections describe the available branch node types.
|
||||
|
||||
#### Object nodes
|
||||
|
||||
An object node it a TypeScript-like object with one or more named child properties. The object node's properties can in principle be any of the node types including branch node types; but typically the schema for the `SharedTree` that your code defines will specify for any object node a specific set of properties and node types of each. A `SharedTree` can have many object nodes at various places in the tree and they do not all have to conform to the same schema. Your schema can specify different properties for different object nodes. The schema also specifies whether a child property is required or optional, and it can assign a union datatype to any property. For example, a property could be either number or string.
|
||||
|
||||
For information about creating the schema for an object node, see [Object schema](#object-schema). For information about adding an object node to the the `SharedTree` and about reading and writing to an object node, see [Object node APIs](#object-node-apis).
|
||||
|
||||
#### Map nodes
|
||||
|
||||
A map node is a set of zero or more key-value pairs similar to a JavaScript Map object, but the keys can only be strings. The schema for the `SharedTree` that your code defines will specify the possible node types that can be values of the keys. It can specify that all node types are allowed or only a subset. There is no way to specify different subsets of node types for different keys.
|
||||
|
||||
The schema for a map node cannot specify particular key names, nor can it specify a maximum or minimum number of key-value pairs.
|
||||
|
||||
For information about creating the schema for a map node, see [Map schema](#map-schema). For information about adding a map node to the the `SharedTree` and about reading and writing to a map node, see [Map node APIs](#map-node-apis).
|
||||
|
||||
#### Array nodes
|
||||
|
||||
An array node is an indexed sequence of zero or more values like a JavaScript array. In principle, values can be any of the node types, but the schema that your code defines will specify what subset of those types can be the values of any given array item.
|
||||
|
||||
For information about creating the schema for an array node, see [Array schema](#array-schema). For information about adding an array node to the the `SharedTree` and about reading and writing to an array node, see [Array node APIs](#array-node-apis).
|
||||
|
||||
## Installation
|
||||
|
||||
The `SharedTree` library can be found in the [fluid-framework](https://www.npmjs.com/package/fluid-framework) package (version 2.x).
|
||||
|
||||
To get started, run the following from a terminal in your project folder:
|
||||
|
||||
```bash
|
||||
npm install fluid-framework@canary
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The major programming tasks for using `SharedTree`s are:
|
||||
|
||||
- Define a schema for the `SharedTree`. As you build out from prototype to full production application, you can add to this schema and create additional schemas for additional `ShareTree`s. See [Schema definition](#schema-definition).
|
||||
- Create the `SharedTree` object. See [Creation](#creation).
|
||||
- Create code that reads and writes to the nodes of the `SharedTree`. See [API](#api).
|
||||
|
||||
### Schema definition
|
||||
|
||||
Start by creating a `SchemaFactory` object. The following is an example. Note that the parameter must be some unique string such as a UUID.
|
||||
|
||||
```typescript
|
||||
import { ... SchemaFactory, ... } from '@fluid-experimental/tree2';
|
||||
|
||||
const sf = new SchemaFactory('ec1db2e8-0a00-11ee-be56-0242ac120002');
|
||||
```
|
||||
|
||||
The `SchemaFactory` class defines five primitive data types; `boolean`, `string`, `number`, `null`, and `handle` for specifying leaf nodes. It also has three methods for specifying branch nodes; `object()`, `array()`, and `map()`. Use the members of the class to build a schema.
|
||||
|
||||
As an example, consider an app that provides a digital board with groups of sticky notes as shown in the following screenshot:
|
||||
|
||||
![A screenshot of a sticky note board app](/images/sticky-note-board-app.png)
|
||||
|
||||
The full sample is at: [Shared Tree Demo](https://github.com/microsoft/FluidExamples/tree/main/brainstorm). *The code snippets in this article are simplified versions of the code in the sample.*
|
||||
|
||||
#### Object schema
|
||||
|
||||
Use the `object()` method to create a schema for a note. Note the following about this code:
|
||||
|
||||
- The `object()`, `array()`, and `map()` methods return an object that defines a schema. Notionally, you can think of this object as datatype. (In the next step, you covert it to an actual TypeScript type.)
|
||||
- The first parameter of `object()` is the name of the type.
|
||||
- The `id`, `text`, `author`, and `lastChanged` properties are leaf nodes.
|
||||
- The `votes` property is an array node, whose members are all strings. It is defined with an inline call of the `array()` method.
|
||||
|
||||
```typescript
|
||||
const noteSchema = sf.object('Note', {
|
||||
id: sf.string,
|
||||
text: sf.string,
|
||||
author: sf.string,
|
||||
lastChanged: sf.number,
|
||||
votes: sf.array(sf.string),
|
||||
});
|
||||
```
|
||||
|
||||
Create a TypeScript datatype by extending the notional type object.
|
||||
|
||||
```typescript
|
||||
class Note extends noteSchema { /* members of the class defined here */ };
|
||||
```
|
||||
|
||||
You can also make the call of the `object()` method inline as in the following:
|
||||
|
||||
```typescript
|
||||
class Note extends sf.object('Note', {
|
||||
id: sf.string,
|
||||
text: sf.string,
|
||||
author: sf.string,
|
||||
lastChanged: sf.number,
|
||||
votes: sf.array(sf.string),
|
||||
}) { /* members of the class defined here */ };
|
||||
```
|
||||
|
||||
For the remainder of this article, we use the inline style.
|
||||
|
||||
You can add fields, properties, and methods like any TypeScript class including methods that wrap one or more methods in the `SharedTree` [APIs](#api). For example, the `Node` class can have the following `updateText` method. Since the method writes to shared properties, the changes are reflected on all clients.
|
||||
|
||||
```typescript
|
||||
public updateText(text: string) {
|
||||
this.lastChanged = new Date().getTime();
|
||||
this.text = text;
|
||||
}
|
||||
```
|
||||
|
||||
You can also add members that affect only the current client; that is, they are not based on DDSes. For example, the sticky note application can be updated to let each user set their own color to any note without changing the color of the note on any other clients. To facilitate this feature, the following members could be added to the `Note` class. Since the `color` property is not a shared object, the changes made by `setColor` only affect the current client.
|
||||
|
||||
```typescript
|
||||
private color: string = "yellow";
|
||||
|
||||
public setColor(newColor: string) {
|
||||
this.color = newColor;
|
||||
}
|
||||
```
|
||||
|
||||
{{< callout note >}}
|
||||
|
||||
Do *not* override the constructor of types that you derive from objects returned by the `object()`, `array()`, and `map()` methods of `SchemaFactory`. Doing so has unexpected effects.
|
||||
|
||||
{{< /callout >}}
|
||||
|
||||
Create the schema for a group of notes. Note that the `array()` method is called inline, which means that the `Group.notes` property has the notional datatype of an array node. We'll change this to a genuine TypeScript type in the [Array schema](#array-schema) section.
|
||||
|
||||
```typescript
|
||||
class Group extends sf.object('Group', {
|
||||
id: sf.string,
|
||||
name: sf.string,
|
||||
notes: sf.array(Note),
|
||||
});
|
||||
```
|
||||
|
||||
#### Array schema
|
||||
|
||||
The app is going to need the type that is returned from `sf.array(Note)` in multiple places, including outside the context of `SchemaFactory`, so we create a TypeScript type for it as follows. Note that we include a method for adding a new note to the array of notes. The implementation is omitted, but it would wrap the constructor for the `Note` class and one or more methods in the [Array node APIs](#array-node-apis).
|
||||
|
||||
```typescript
|
||||
class Notes extends sf.array('Notes', Note) {
|
||||
public newNote(author: string) {
|
||||
// implementation omitted.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now revise the declaration of the `Group` class to use the new type.
|
||||
|
||||
```typescript
|
||||
class Group extends sf.object('Group', {
|
||||
id: sf.string,
|
||||
name: sf.string,
|
||||
notes: Notes,
|
||||
});
|
||||
```
|
||||
|
||||
#### Root schema
|
||||
|
||||
As you can see from the screenshot, the top level of the root of the app's data can have two kinds of children: notes in groups and notes that are outside of any group. So, the children are defined as `Items` which is an array with two types of items. This is done by passing an array of schema types to the `array()` method. Methods for adding a new group to the app and a new note that is outside of any group are included.
|
||||
|
||||
```typescript
|
||||
class Items extends sf.array('Items', [Group, Note]) {
|
||||
public newNote(author: string) {
|
||||
// implementation omitted.
|
||||
}
|
||||
|
||||
public newGroup(name: string): Group {
|
||||
// implementation omitted.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The root of the schema must itself have a type which is defined as follows:
|
||||
|
||||
```typescript
|
||||
class App extends sf.object('App', {
|
||||
items: Items,
|
||||
}) {}
|
||||
```
|
||||
|
||||
The final step is to create a configuration object that will be used when a `SharedTree` object is created. See [Creation](#creation). The following is an example of doing this. Note that the second parameter returns an object that initializes the tree with an object that must conform to the root schema, `App`. So in this example, it has a single `items` property. The value of the `items` property specifies that the items array is empty. It is not a requirement that the initial tree be empty: you can assign one or more groups or notes to the initial tree.
|
||||
|
||||
```typescript
|
||||
export const appTreeConfiguration = new TreeConfiguration(
|
||||
App, // root node
|
||||
() => ({
|
||||
// initial tree
|
||||
items: [],
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
#### Map schema
|
||||
|
||||
The sticky notes example doesn't have any map branches, but creating a map schema is like creating an array schema, except that you use the `map()` method. Consider a silent auction app. Users view various items up for auction and place bids for items they want. One way to represent the bids for an item is with a map from user names to bids. The following snippet shows how to create the schema. Note that `map()` doesn't need a parameter to specify the type of keys because it is always string.
|
||||
|
||||
```typescript
|
||||
class AuctionItem extends sf.map('AuctionItem', sf.number) { ... }
|
||||
```
|
||||
|
||||
Like `array()`, `map()` can accept an array of types when the values of the map are not all the same type.
|
||||
|
||||
```typescript
|
||||
class MyMapSchema extends sf.map('MyMap', [sf.number, sf.string]) { ... }
|
||||
```
|
||||
|
||||
#### Setting properties as optional
|
||||
|
||||
To specify that a property is not required, pass it to the `SchemaFactory.optional()` method inline. The following example shows a schema with two optional properties.
|
||||
|
||||
```typescript
|
||||
class Proposal = sf.object('Proposal', {
|
||||
id: sf.string,
|
||||
text: sf.optional(sf.string),
|
||||
comments: sf.optional(sf.array(Comment)),
|
||||
});
|
||||
```
|
||||
|
||||
### Creation
|
||||
|
||||
To create a `SharedTree` object, create a container with an initial object of that type and then apply the schema to it. The code in this section continues the sticky note example. Start by creating a container schema with an initial object of type `SharedTree` and use it to create a container.
|
||||
|
||||
```typescript
|
||||
const containerSchema: ContainerSchema = {
|
||||
initialObjects: {
|
||||
appData: ISharedTree,
|
||||
},
|
||||
};
|
||||
|
||||
const { container, services } = await client.createContainer(containerSchema);
|
||||
```
|
||||
|
||||
Apply the schema to the tree by passing the tree configuration object to the `ITree.schematize()` method.
|
||||
|
||||
```typescript
|
||||
const stickyNotesTree = container.initialObjects.appData as ITree;
|
||||
|
||||
stickyNotesTree.schematize(appTreeConfiguration);
|
||||
```
|
||||
|
||||
You can now add child items to the `stickyNotesTree` object using the methods described in [API](#api) below.
|
||||
|
||||
### API
|
||||
|
||||
The `SharedTree` object provides methods that enable your code to add nodes to the tree, remove nodes, and move nodes within the tree. You can also set and read the values of leaf nodes. The APIs have been designed to match as much as possible the syntax of TypeScript primitives, objects, maps, and arrays; although it is not possible to match exactly.
|
||||
|
||||
#### Leaf node APIs
|
||||
|
||||
Leaf nodes are read and written exactly the way JavaScript primitive types are by using dot notation and the assignment operator (`=`). The following example shows how to write to a leaf node:
|
||||
|
||||
```typescript
|
||||
myNewsPaperTree.articles[1].headline = "Man bites dog";
|
||||
```
|
||||
|
||||
The following examples show how to read from a leaf node. *Note that the datatype of `pointsForDetroitTigers` is `number`, not `sf.number`.* This is a general principle: the value returned from a leaf node, other than a `FluidHandle` node, is the underlying JavaScript primitive type.
|
||||
|
||||
```typescript
|
||||
const pointsForDetroitTigers: number = seasonTree.tigersTeam.game1.points;
|
||||
```
|
||||
|
||||
#### Object node APIs
|
||||
|
||||
Your code reads object nodes and their properties exactly as it would read a JavaScript object. The following are some examples.
|
||||
|
||||
```typescript
|
||||
const pointsForDetroitTigers: number = seasonTree.tigersTeam.game1.points;
|
||||
|
||||
const counterHandle: FluidHandle = myTree.myObjectNode.myHandle;
|
||||
|
||||
const myItems: Array = stickyNotesTree.items;
|
||||
```
|
||||
|
||||
To write to an object node, you first create an object and then assign it to the node with the assignment operator (`=`). If the object node is a child of a map or array node, use the write [Map node write APIs](#map-node-write-apis) or [Array node write APIs](#array-node-write-apis).
|
||||
|
||||
You must create the object using the constructor of the class that you derived from the object returned by `SchemaFactory.object()` method. The following shows how to create a note object from the sticky notes example.
|
||||
|
||||
```typescript
|
||||
const babyShowerNote = new Note({
|
||||
id: Guid.create().toString(),
|
||||
text: "Baby shower is at 3 PM today.",
|
||||
author: "Bob",
|
||||
lastChanged: 19697 // Days since January 1, 1970, the Unix epoch.
|
||||
votes: ["0"]
|
||||
});
|
||||
```
|
||||
|
||||
We show how to add this note to an array of notes in the tree in [Array node APIs](#array-node-apis).
|
||||
|
||||
#### Map node APIs
|
||||
|
||||
##### Map node read APIs
|
||||
|
||||
The read APIs for map nodes have the same names and syntax as the corresponding APIs for JavaScript Map objects.
|
||||
|
||||
```typescript
|
||||
has(key): boolean
|
||||
```
|
||||
|
||||
Returns `true`` if the key is present in the map.
|
||||
|
||||
```typescript
|
||||
get(key): T | undefined
|
||||
```
|
||||
|
||||
Returns the value of the property with the specified key.
|
||||
|
||||
```typescript
|
||||
keys(): IterableIterator<string>
|
||||
```
|
||||
|
||||
Returns an Iterator that contains the keys in the map node. The keys are iterated in the order that they were added.
|
||||
|
||||
```typescript
|
||||
values(): IterableIterator<T>
|
||||
```
|
||||
|
||||
Returns an Iterator that contains the values in the map node. The values are iterated in the order that they were added.
|
||||
|
||||
```typescript
|
||||
entries(): IterableIterator<[string, T]>
|
||||
```
|
||||
|
||||
Returns an Iterator that contains the key/value pairs in the map node. The pairs are iterated in the order that they were added.
|
||||
|
||||
```typescript
|
||||
map(callback: ()=>[]): IterableIterator<[string, T]>
|
||||
```
|
||||
|
||||
Returns an array, *not a map node or array node*, that is a result of applying the callback parameter to each member of the original map node. It is just like [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
|
||||
|
||||
##### Map node write APIs
|
||||
|
||||
The write methods for map nodes are also the same as the corresponding methods for JavaScript `Map` objects.
|
||||
|
||||
```typescript
|
||||
set(key: string, value: T)
|
||||
```
|
||||
|
||||
The `set()` method sets/changes the value of the item with the specified key. If the key is not present, the item is added to the map. Note the following:
|
||||
|
||||
- The `T` can be any type that conforms to the map node's schema. For example, if the schema was defined with `class MyMap extends sf.map([sf.number, sf.string]);`, then `T` could be `number` or `string`.
|
||||
- If multiple clients set the same key simultaneously, the key gets the value set by the last edit to apply. For the meaning of "simultaneously", see [Types of distributed data structures]({{< relref "overview.md" >}}).
|
||||
|
||||
```typescript
|
||||
delete(key: string): boolean
|
||||
```
|
||||
|
||||
The `delete()` method removes the item with the specified key. If the key is not present, the method returns `false`. If one client sets a key and another deletes it simultaneously, the key is deleted only if the deletion op is the last one applied. For the meaning of "simultaneously", see [Types of distributed data structures]({{< relref "overview.md" >}}).
|
||||
|
||||
##### Map node properties
|
||||
|
||||
```typescript
|
||||
size: number
|
||||
```
|
||||
|
||||
The total number of entries in the map node.
|
||||
|
||||
#### Array node APIs
|
||||
|
||||
##### Array node read APIs
|
||||
|
||||
Array nodes have all the same non-mutating read methods as the JavaScript [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) type. (For information about the differences between mutating and non-mutating methods, see [Copying methods and mutating methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#copying_methods_and_mutating_methods)). Note that methods which return an array, like `Array.map()`, when called on an array node, return a JavaScript array, not an object of the type of the array node. For example, if the type is `Notes` from the sticky notes example, an array is returned, not a `Notes` object.
|
||||
|
||||
##### Array node write APIs
|
||||
|
||||
The write APIs for array nodes are quite different from JavaScript arrays. They are more suitable for data items that are being worked on collaboratively by multiple people. There are three categories of write APIs: Insert, Remove, and Move.
|
||||
|
||||
###### Insert methods
|
||||
|
||||
Array nodes have three methods that insert new items into the node. Note that in all of the following, the `T` can be any type that conforms to the array node's schema. For example, if the schema was defined with `class MyArray extends sf.array([sf.number, sf.string]);`, then `T` could be `number` or `string`.
|
||||
|
||||
```typescript
|
||||
insertAt(index: number, value: Iterable<T>)
|
||||
```
|
||||
|
||||
Inserts the provided value(s) at the specified `index`. If the `index` is greater than the length of the array, the items are inserted at the end of the array.
|
||||
|
||||
```typescript
|
||||
insertAtStart(value: Iterable<T>)
|
||||
```
|
||||
|
||||
Inserts the provided value(s) at the start of the array. This is sugar for `insertAt(0, …)`.
|
||||
|
||||
```typescript
|
||||
insertAtEnd(value: Iterable<T>)
|
||||
```
|
||||
|
||||
Inserts the provided value(s) at the end of the array. This is syntactic sugar for `insertAt(Infinity, …)`.
|
||||
|
||||
###### Remove methods
|
||||
|
||||
Array nodes have two methods that remove items from the node. Note the following about these methods:
|
||||
|
||||
- Removed items are saved internally for a time in case they need to be restored as a result of an undo operation.
|
||||
- A removed item may be restored as a result of a simultaneous move operation from another client. For example, if one client removes items 3-5, and another client simultaneously moves items 4 and 5, then only item 3 is removed. The other two are moved, regardless of the order of the move and remove operations.
|
||||
- Removal of items never overrides inserting items. For example, if one client removes items 10-15, and another client simultaneously inserts an item at index 12, the original items 10-15 are removed, but new item is inserted between item 9 and the item that used to be at index 16. This happens regardless of the order of the remove and insert operations.
|
||||
|
||||
For the meaning of "simultaneously", see [Types of distributed data structures]({{< relref "overview.md" >}}).
|
||||
|
||||
```typescript
|
||||
removeAt(index: number)
|
||||
```
|
||||
|
||||
Removes the item at the given `index`.
|
||||
|
||||
```typescript
|
||||
removeRange(start?: number, end?: number)
|
||||
```
|
||||
|
||||
Removes the items indicated by the `start` index (inclusive) and `end` index (exclusive). If the end index is omitted, every item from the start index to the end of the array is removed. If the start index is omitted, it defaults to 0. So, calling `removeRange()` removes all the items in the array.
|
||||
|
||||
###### Move methods
|
||||
|
||||
Array nodes have three methods that move items within an array or from one array node to another. When moving from one array node to another, these methods must be called from the destination array node. Note that in all of the following, the `T` can be any type that is derived from an object that is returned by a call of `SchemaFactory.array()`, such as the `Notes` and `Items` classes in the sticky notes example.
|
||||
|
||||
```typescript
|
||||
moveToStart(sourceStartIndex: number, sourceEndIndex: number, source?: T)
|
||||
```
|
||||
|
||||
Moves the specified items to the start of the array. Specify a `source` array if it is different from the destination array.
|
||||
|
||||
```typescript
|
||||
moveToEnd(sourceStartIndex: number, sourceEndIndex: number, source?: T)
|
||||
```
|
||||
|
||||
Moves the specified items to the end of the array. Specify a `source` array if it is different from the destination array.
|
||||
|
||||
```typescript
|
||||
moveToIndex(index: number, sourceStartIndex: number, sourceEndIndex: number, source?: T)
|
||||
```
|
||||
|
||||
Moves the items to the specified `index` in the destination array. The item that is at `index` before the method is called will be at the first index position that follows the moved items after the move. Specify a `source` array if it is different from the destination array. If the items are being moved within the same array, the `index` position is calculated including the items being moved.
|
||||
|
||||
### Events
|
||||
|
||||
The `SharedTree` object supports two events: `beforeChange` and `afterChange`. Your code can create handlers for these events using the utility class `Tree`. See [Tree utility APIs](#tree-utility-apis).
|
||||
|
||||
## Tree utility APIs
|
||||
|
||||
The `Tree` class provides some static utility APIs for working with `ShareTree` objects.
|
||||
|
||||
## Event handling
|
||||
|
||||
```typescript
|
||||
Tree.on(node: SharedTreeNode, eventType: string, listener: () => void): () => void
|
||||
```
|
||||
|
||||
Assigns the specified `listener` function to the specified `eventType` for the specified `node`. The `node` can be any node of the tree. The `eventType` can be either "afterChange" or "beforeChange". An `event` object is automatically passed to the `listener`. It has three members:
|
||||
|
||||
- `event.target`: The node on which the event was triggered.
|
||||
- `event.isLocal`: Specifies whether the change was made on the local client or a remote client.
|
||||
- `event.stopPropagation()`: If called in the listener, it stops the event from being triggered on the parent, in the tree, of the `event.target`.
|
||||
|
||||
The `Tree.on()` method returns a function that unsubscribes the handler from the event. This method is typically called in clean up code when the node is being removed.
|
||||
|
||||
## Type guard
|
||||
|
||||
When your code needs to process nodes only of a certain type and it has a reference to an object of an unknown type, you can use the TypeScript `instanceOf` keyword to test for the desired type as in the following examples.
|
||||
|
||||
```typescript
|
||||
if (myNode instanceOf sf.number) {
|
||||
// Code here that processes number nodes.
|
||||
}
|
||||
|
||||
if (myNode instanceOf Note) {
|
||||
// Code here that processes Note nodes.
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, the `Tree` class provides a method for testing the type of a node:
|
||||
|
||||
```typescript
|
||||
Tree.is(someNode: SharedTreeNode, nodeType: TreeNodeSchema | T): boolean
|
||||
```
|
||||
|
||||
Returns `true` if `someNode` is of type `nodeType`. Note that `T` is a type that is derived from a call of one of the `SchemaFactory` methods; `object()`, `map()`, or `array()`. Here are examples:
|
||||
|
||||
```typescript
|
||||
if (Tree.is(myNode, sf.number)) {
|
||||
// Code here that processes number nodes.
|
||||
}
|
||||
|
||||
if (Tree.is(myNode, Note)) {
|
||||
// Code here that processes Note nodes.
|
||||
}
|
||||
```
|
||||
|
||||
For another example, see the `Tree.parent()` method in [Node information](#node-information).
|
||||
|
||||
## Node information
|
||||
|
||||
```typescript
|
||||
Tree.key(node: SharedTreeNode): number | string
|
||||
```
|
||||
|
||||
Returns the key of the `node`. This is a string in all cases, except an array node, in which case it returns the index of the node.
|
||||
|
||||
```typescript
|
||||
Tree.parent(node: SharedTreeNode): SharedTreeNode
|
||||
```
|
||||
|
||||
Returns the parent node of `node`. The following snippet continues the sticky notes example. Suppose that you have a reference to a note object and you want to delete it if, and only if, it is a member of an array of notes in a group or it is a direct child of the root. You can get the parent node and test what its type is.
|
||||
|
||||
```typescript
|
||||
const parent = Tree.parent(note);
|
||||
|
||||
if ((parent instanceOf Notes) || (parent instanceOf Items)) {
|
||||
const index = parent.indexOf(note);
|
||||
parent.removeAt(index);
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
Tree.status(node: SharedTreeNode): TreeStatus
|
||||
```
|
||||
|
||||
Returns the current status of `node`. Possible values are:
|
||||
|
||||
- **InDocument**: The node is in the tree.
|
||||
- **Removed**: The node has been removed from the tree but is still restorable by undo.
|
||||
- **Deleted**: The node is deleted and unrestorable.
|
||||
|
||||
```typescript
|
||||
Tree.schema(node: SharedTreeNode): TreeNodeSchema
|
||||
```
|
||||
|
||||
Returns the object that defines the schema of the `node` object.
|
||||
|
||||
## API Documentation
|
||||
|
||||
For a comprehensive view of the `SharedTree` package's API documentation, see [the SharedTree API docs]({{< packageref "tree" >}}).
|
|
@ -15,7 +15,7 @@ how to combine those distributed data structures with custom code (business logi
|
|||
argument) and then run "npm run build:md-magic" from the docs folder. That will update all autogenerated
|
||||
content, so you should commit the resulting changes. -->
|
||||
|
||||
<!-- AUTO-GENERATED-CONTENT:START (INCLUDE:path=../../../../packages/framework/aqueduct/README.md&start=23&end=-27) -->
|
||||
<!-- AUTO-GENERATED-CONTENT:START (INCLUDE:path=../../../../packages/framework/aqueduct/README.md&start=17&end=-27) -->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- NOTE: This section is automatically generated by embedding the referenced file contents. Do not update these generated contents directly. -->
|
||||
|
@ -239,15 +239,16 @@ makes a request to the Container for `{url:"color"}` will intercept and return a
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -112,15 +112,16 @@ object of the correct type or `undefined`.
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -138,15 +138,16 @@ As the Fluid Framework expands, we intend to make further use of these responses
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ menuPosition: 2
|
|||
---
|
||||
|
||||
[Azure Fluid Relay](https://aka.ms/azurefluidrelay) is a cloud-hosted Fluid service.
|
||||
You can connect your Fluid application to an Azure Fluid Relay instance using the `AzureClient` in the [@fluidframework/azure-client]({{< relref "/docs/apis/azure-client.md" >}}) package.
|
||||
You can connect your Fluid application to an Azure Fluid Relay instance using the `AzureClient` in the [@fluidframework/azure-client]({{< packageref "azure-client" "v2" >}}) package.
|
||||
AzureClient handles the logic of connecting your [Fluid container]({{< relref "containers.md" >}}) to the service while keeping the container object itself service-agnostic.
|
||||
You can use one instance of this client to manage multiple containers.
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ The Fluid Framework can be used with any compatible service implementation. Some
|
|||
|
||||
## Tinylicious
|
||||
|
||||
[Tinylicious]({{< relref "tinylicious.md" >}}) is a minimal, self-contained implementation of the Fluid Framework service that is much smaller (tinier!) than Routerlicious, the reference implementation of the service.
|
||||
[Tinylicious]({{< packageref "tinylicious" >}}) is a minimal, self-contained implementation of the Fluid Framework service that is much smaller (tinier!) than Routerlicious, the reference implementation of the service.
|
||||
|
||||
Tinylicious is intended for testing and development only.
|
||||
|
||||
|
@ -19,7 +19,7 @@ The easiest way to try out Fluid is with Tinylicious or Azure Fluid Relay.
|
|||
|
||||
## Azure Fluid Relay
|
||||
|
||||
Microsoft [Azure Fluid Relay](https://aka.ms/azurefluidrelay) is a hosted Fluid service. You can [provision Fluid Relay services](https://docs.microsoft.com/azure/azure-fluid-relay/how-tos/provision-fluid-azure-portal) as part of your Microsoft Azure subscription and use the [@fluidframework/azure-client]({{< relref "azure-client.md" >}}) library to create and load Fluid containers.
|
||||
Microsoft [Azure Fluid Relay](https://aka.ms/azurefluidrelay) is a hosted Fluid service. You can [provision Fluid Relay services](https://docs.microsoft.com/azure/azure-fluid-relay/how-tos/provision-fluid-azure-portal) as part of your Microsoft Azure subscription and use the [@fluidframework/azure-client]({{< packageref "azure-client" >}}) library to create and load Fluid containers.
|
||||
|
||||
Learn more in the [Azure Fluid Relay documentation](https://aka.ms/azurefluidrelaydocs).
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: Connect to Azure Fluid Relay
|
||||
menuPosition: 2
|
||||
---
|
||||
|
||||
[SharePoint Embedded](https://aka.ms/azurefluidrelay) is a cloud-hosted Fluid service.
|
||||
You can connect your Fluid application to an Azure Fluid Relay instance using the `AzureClient` in the [@fluidframework/azure-client]({{< relref "/docs/api/v1/azure-client.md" >}}) package.
|
||||
AzureClient handles the logic of connecting your [Fluid container]({{< relref "containers.md" >}}) to the service while keeping the container object itself service-agnostic.
|
||||
You can use one instance of this client to manage multiple containers.
|
||||
|
||||
To learn more about using AzureClient and Azure Fluid Relay, see [Connect to an Azure Fluid Relay instance](https://docs.microsoft.com/azure/azure-fluid-relay/how-tos/connect-fluid-azure-service).
|
|
@ -273,15 +273,16 @@ When you make changes to the code the project will automatically rebuild and the
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -396,15 +396,16 @@ When you make changes to the code the project will automatically rebuild and the
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -212,15 +212,16 @@ When you make changes to the code the project will automatically rebuild and the
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -255,15 +255,16 @@ When you make changes to the code the project will automatically rebuild and the
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Examples
|
||||
menuPosition: 4
|
||||
menuPosition: 5
|
||||
aliases:
|
||||
- "/docs/get-started/examples/"
|
||||
- "/start/examples/"
|
||||
|
@ -9,51 +9,16 @@ aliases:
|
|||
We've included several example apps in a [GitHub repository](https://github.com/microsoft/FluidExamples/) to demonstrate
|
||||
both the power and simplicity of Fluid. Use these to learn and kickstart your own projects.
|
||||
|
||||
## Simple SharedTree Example
|
||||
|
||||
![A screenshot of simple shared tree app](/images/simple-example.png)
|
||||
|
||||
The [simple SharedTree example app](https://github.com/microsoft/FluidExamples/tree/main/item-counter) shows how to create a React web app using the SharedTree data structure. This example is designed to be a good starting point for building more sophisticated apps.
|
||||
|
||||
## Brainstorming
|
||||
|
||||
![A screenshot of brainstorming app](/images/brainstorm-example.png)
|
||||
|
||||
The sticky notes [brainstorming app](https://github.com/microsoft/FluidExamples/tree/main/brainstorm)
|
||||
shows how simple experiences become compelling when you make them collaborative. This example uses distributed
|
||||
maps (SharedMaps) to update the state of sticky notes as well as keep track of who added which ideas and who
|
||||
voted for those ideas.
|
||||
shows how simple experiences become compelling when you make them collaborative. This example uses multiple SharedTree data structures to create, update, and organize sticky notes.
|
||||
|
||||
## Collaborative text area
|
||||
|
||||
The [collaborative text area app](https://github.com/microsoft/FluidExamples/tree/main/collaborative-text-area/) shows
|
||||
how to create a text area that can be collaboratively edited by multiple clients. It uses React to create
|
||||
the view. See also [Building a collaborative TextArea]({{< relref "docs/recipes/collaborative-text-area.md" >}}).
|
||||
|
||||
## Separating the view from the Fluid business logic
|
||||
|
||||
The [multiframework dice roller app](https://github.com/microsoft/FluidExamples/tree/main/multi-framework-diceroller/)
|
||||
shows you how to keep your view layer separate from your Fluid layer. By changing a single line
|
||||
of code, you can switch between views based on React, Vue, Web Components, and simple, no framework
|
||||
JavaScript. See also [Using Fluid with React]({{< relref "docs/recipes/react.md" >}}),
|
||||
[Using Fluid with Vue]({{< relref "docs/recipes/vue.md" >}}),
|
||||
and [Using Fluid with Web Components]({{< relref "docs/recipes/web-components.md" >}})
|
||||
|
||||
## Angular and Fluid
|
||||
|
||||
The [Angular timestamp app](https://github.com/microsoft/FluidExamples/tree/main/angular-demo/) shows how clients
|
||||
can share a timestamp. Use it as a starter template to build your own Fluid Framework application on the
|
||||
Angular framework. See also [Using Fluid with Angular]({{< relref "docs/recipes/angular.md" >}}).
|
||||
|
||||
## React and Fluid
|
||||
|
||||
The [React dice app](https://github.com/microsoft/FluidExamples/tree/main/react-starter-template/) shows how
|
||||
to make incorporate Fluid state into a React-based app. Use it as a starter template to implement a
|
||||
React-based view for your own Fluid Framework application.
|
||||
|
||||
The [React timestamp app](https://github.com/microsoft/FluidExamples/tree/main/react-demo) shows how to integrate Fluid into an app created with the [create-react-app](https://create-react-app.dev/) tool. See also [Using Fluid with React]({{< relref "docs/recipes/react.md" >}}).
|
||||
|
||||
## Fluid with command line clients
|
||||
|
||||
The [NodeJS demo app](https://github.com/microsoft/FluidExamples/tree/main/node-demo) shows how clients
|
||||
that don't have an HTTP canvas can participate in the Fluid Framework collaboration. See also
|
||||
[Using Fluid with NodeJS]({{< relref "docs/recipes/node.md" >}}).
|
||||
|
||||
## Fluid in a Microsoft 365 Teams tab
|
||||
|
||||
The [Using Fluid with Microsoft Teams](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/using-fluid-msteam)
|
||||
article shows you how to integrate a Fluid Framework application into a custom Microsoft 365 Teams tab.
|
||||
|
|
После Ширина: | Высота: | Размер: 66 KiB |
|
@ -12,6 +12,12 @@ aliases:
|
|||
In this Quick Start you will be getting a dice roller Fluid application up and running first on your computer's
|
||||
localhost.
|
||||
|
||||
{{< callout note >}}
|
||||
|
||||
The demo app uses Fluid Framework 2.0, which is in preview.
|
||||
|
||||
{{< /callout >}}
|
||||
|
||||
{{< fluid_bundle_loader idPrefix="dice-roller"
|
||||
bundleName="dice-roller.2021-09-24.js" >}}
|
||||
|
||||
|
|
|
@ -8,6 +8,13 @@ aliases:
|
|||
|
||||
In this walkthrough, you'll learn about using the Fluid Framework by examining the DiceRoller application at <https://github.com/microsoft/FluidHelloWorld>. To get started, go through the [Quick Start]({{< relref "quick-start.md" >}}) guide.
|
||||
|
||||
{{< callout note >}}
|
||||
|
||||
The demo app uses Fluid Framework 2.0, which is in preview.
|
||||
|
||||
{{< /callout >}}
|
||||
|
||||
|
||||
{{< fluid_bundle_loader idPrefix="dice-roller"
|
||||
bundleName="dice-roller.2021-09-24.js" >}}
|
||||
|
||||
|
@ -29,16 +36,13 @@ The app creates Fluid containers using a schema that defines a set of *initial o
|
|||
Lastly, `root` defines the HTML element that the Dice will render on.
|
||||
|
||||
```js
|
||||
import { SharedMap } from "fluid-framework";
|
||||
import { SharedTree, TreeConfiguration, SchemaFactory, Tree } from "fluid-framework";
|
||||
import { TinyliciousClient } from "@fluidframework/tinylicious-client";
|
||||
|
||||
export const diceValueKey = "dice-value-key";
|
||||
|
||||
const client = new TinyliciousClient();
|
||||
|
||||
const containerSchema = {
|
||||
initialObjects: { diceMap: SharedMap }
|
||||
};
|
||||
initialObjects: { diceTree: SharedTree },
|
||||
};
|
||||
|
||||
const root = document.getElementById("content");
|
||||
```
|
||||
|
@ -63,15 +67,12 @@ The `renderDiceRoller` function is created in a later step. It renders the UI of
|
|||
|
||||
```js
|
||||
const createNewDice = async () => {
|
||||
const { container } = await client.createContainer(containerSchema);
|
||||
// Set default data
|
||||
container.initialObjects.diceMap.set(diceValueKey, 1);
|
||||
// Attach container to service and return assigned ID
|
||||
const id = container.attach();
|
||||
// Load the dice roller
|
||||
renderDiceRoller(container.initialObjects.diceMap, root);
|
||||
return id;
|
||||
}
|
||||
const { container } = await client.createContainer(containerSchema);
|
||||
const dice = container.initialObjects.diceTree.schematize(treeConfiguration).root;
|
||||
const id = await container.attach();
|
||||
renderDiceRoller(dice, root);
|
||||
return id;
|
||||
}
|
||||
```
|
||||
|
||||
### Loading an existing container
|
||||
|
@ -80,10 +81,10 @@ Loading a container is more straightforward than creating a new one. When loadin
|
|||
|
||||
```js
|
||||
const loadExistingDice = async (id) => {
|
||||
const { container } = await client.getContainer(id, containerSchema);
|
||||
renderDiceRoller(container.initialObjects.diceMap, root);
|
||||
const { container } = await client.getContainer(id, containerSchema);
|
||||
const dice = container.initialObjects.diceTree.schematize(treeConfiguration).root;
|
||||
renderDiceRoller(dice, root);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Switching between loading and creating
|
||||
|
@ -99,12 +100,12 @@ The decision logic is implemented in a `start` function which is immediately cal
|
|||
|
||||
```js
|
||||
async function start() {
|
||||
if (location.hash) {
|
||||
await loadExistingDice(location.hash.substring(1))
|
||||
} else {
|
||||
const id = await createNewDice();
|
||||
location.hash = id;
|
||||
}
|
||||
if (location.hash) {
|
||||
await loadExistingDice(location.hash.substring(1));
|
||||
} else {
|
||||
const id = await createNewDice();
|
||||
location.hash = id;
|
||||
}
|
||||
}
|
||||
|
||||
start().catch((error) => console.error(error));
|
||||
|
@ -131,11 +132,11 @@ diceTemplate.innerHTML = `
|
|||
<button class="roll"> Roll </button>
|
||||
</div>
|
||||
`
|
||||
const renderDiceRoller = (diceMap, elem) => {
|
||||
elem.appendChild(template.content.cloneNode(true));
|
||||
const renderDiceRoller = (dice, elem) => {
|
||||
elem.appendChild(template.content.cloneNode(true));
|
||||
|
||||
const rollButton = elem.querySelector(".roll");
|
||||
const dice = elem.querySelector(".dice");
|
||||
const rollButton = elem.querySelector(".roll");
|
||||
const diceElem = elem.querySelector(".dice");
|
||||
|
||||
/* REMAINDER OF THE FUNCTION IS DESCRIBED BELOW */
|
||||
}
|
||||
|
@ -147,12 +148,14 @@ Let's go through the rest of the `renderDiceRoller` function line-by-line.
|
|||
|
||||
### Create the Roll button handler
|
||||
|
||||
The next line of the `renderDiceRoller` function assigns a handler to the click event of the "Roll" button. Instead of updating the local state directly, the button updates the number stored in the `value` key of the passed in `diceMap`. Because the `diceMap` is a Fluid `SharedMap`, changes will be distributed to all clients. Any changes to the `diceMap` will cause a `valueChanged` event to be emitted, and an event handler, defined below, can trigger an update of the view.
|
||||
The next line of the `renderDiceRoller` function assigns a handler to the click event of the "Roll" button. Instead of updating the local state directly, the button updates the number stored in the `value` property of the `dice` object. Because `dice` is the root object of Fluid `SharedTree`, changes will be distributed to all clients. Any changes to `dice` will cause a `afterChanged` event to be emitted, and an event handler, defined below, can trigger an update of the view.
|
||||
|
||||
This pattern is common in Fluid because it enables the view to behave the same way for both local and remote changes.
|
||||
|
||||
```js
|
||||
rollButton.onclick = () => diceMap.set(diceValueKey, Math.floor(Math.random() * 6) + 1);
|
||||
rollButton.onclick = () => {
|
||||
dice.value = Math.floor(Math.random() * 6) + 1;
|
||||
}
|
||||
```
|
||||
|
||||
### Relying on Fluid data
|
||||
|
@ -165,30 +168,28 @@ The next line creates the function that will rerender the local view with the la
|
|||
Note that the current value is retrieved from the `SharedMap` each time `updateDice` is called. It is *not* read from the `textContent` of the local `dice` HTML element.
|
||||
|
||||
```js
|
||||
const updateDice = () => {
|
||||
const diceValue = diceMap.get(diceValueKey);
|
||||
// Unicode 0x2680-0x2685 are the sides of a dice (⚀⚁⚂⚃⚄⚅)
|
||||
dice.textContent = String.fromCodePoint(0x267f + diceValue);
|
||||
dice.style.color = `hsl(${diceValue * 60}, 70%, 30%)`;
|
||||
};
|
||||
const updateDice = () => {
|
||||
const diceValue = dice.value;
|
||||
// Unicode 0x2680-0x2685 are the sides of a dice (⚀⚁⚂⚃⚄⚅)
|
||||
diceElem.textContent = String.fromCodePoint(0x267f + diceValue);
|
||||
diceElem.style.color = `hsl(${diceValue * 60}, 70%, 30%)`;
|
||||
}
|
||||
```
|
||||
|
||||
### Update on creation or load of container
|
||||
|
||||
The next line ensures that the dice gets an initial value as soon as `renderDiceRoller` is called, which is when the container is created or loaded.
|
||||
The next line ensures that the dice is rendered as soon as `renderDiceRoller` is called, which is when the container is created or loaded.
|
||||
|
||||
```js
|
||||
updateDice();
|
||||
updateDice();
|
||||
```
|
||||
|
||||
### Handling remote changes
|
||||
|
||||
To keep the data up to date as it changes an event handler must be set on the `diceMap` to call `updateDice` each time that the `valueChanged` event is sent. Note that the `valueChanged` event fires whenever the `diceMap` value changes on *any* client; that is, when the "Roll" button is clicked on any client.
|
||||
|
||||
See the [documentation for SharedMap][SharedMap] to get a list of events fired and the values passed to those events.
|
||||
To keep the data up to date as it changes, an event handler must be set on the `dice` object to call `updateDice` each time that the `afterChanged` event is sent. Use the built-in `Tree` object to subscribe to the event. Note that the `afterChanged` event fires whenever the `dice` object changes on *any* client; that is, when the "Roll" button is clicked on any client.
|
||||
|
||||
```js
|
||||
diceMap.on("valueChanged", updateDice);
|
||||
Tree.on(dice, "afterChange", updateDice);
|
||||
```
|
||||
|
||||
## Run the app
|
||||
|
@ -216,15 +217,16 @@ The [full code for this application is available](https://github.com/microsoft/F
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -315,15 +315,16 @@ It's not recommended to set `localStorage.debug` in code; your users will see a
|
|||
|
||||
<!-- API links -->
|
||||
|
||||
[fluid-framework]: {{< relref "/docs/apis/fluid-framework.md" >}}
|
||||
[@fluidframework/azure-client]: {{< relref "/docs/apis/azure-client.md" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< relref "/docs/apis/tinylicious-client.md" >}}
|
||||
[fluid-framework]: {{< packageref "fluid-framework" "v2" >}}
|
||||
[@fluidframework/azure-client]: {{< packageref "azure-client" "v2" >}}
|
||||
[@fluidframework/tinylicious-client]: {{< packageref "tinylicious-client" "v1" >}}
|
||||
[@fluid-experimental/odsp-client]: {{< packageref "odsp-client" "v2" >}}
|
||||
|
||||
[AzureClient]: {{< relref "/docs/apis/azure-client/AzureClient-class.md" >}}
|
||||
[TinyliciousClient]: {{< relref "/docs/apis/tinylicious-client/TinyliciousClient-class.md" >}}
|
||||
[AzureClient]: {{< apiref "azure-client" "AzureClient" "class" "v2" >}}
|
||||
[TinyliciousClient]: {{< apiref "tinylicious-client" "TinyliciousClient" "class" "v1" >}}
|
||||
|
||||
[FluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[IFluidContainer]: {{< relref "/docs/apis/fluid-static/ifluidcontainer-interface.md" >}}
|
||||
[FluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
[IFluidContainer]: {{< apiref "fluid-static" "IFluidContainer" "interface" "v2" >}}
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@ We are now surfacing errors on FluidContainer "disposed" event, so the applicati
|
|||
|
||||
## fluid-framework
|
||||
|
||||
- Add the missing [ConnectionState]({{< relref "container-loader.md#connectionstate-enum" >}}) export to `fluid-framework`
|
||||
- Add the missing [ConnectionState]({{< packageref "container-loader" "v1" >}}#connectionstate-enum) export to `fluid-framework`
|
||||
|
||||
## @fluidframework/azure-client
|
||||
|
||||
- Fix [AzureClient]({{< relref "azureclient-class.md" >}}) issue where the second user could not connect in `local` mode
|
||||
- Fix [AzureClient]({{< apiref "azure-client" "AzureClient" "class" "v1" >}}) issue where the second user could not connect in `local` mode
|
||||
|
||||
# 1.0.0
|
||||
|
||||
|
@ -38,8 +38,8 @@ We are now surfacing errors on FluidContainer "disposed" event, so the applicati
|
|||
|
||||
We've added two new methods to AzureClient that will enable developers to recover data from corrupted containers. The Fluid Framework automatically generates and saves snapshots of the operation stream that we use to load the latest container. `getContainerVersions` will allow developers to access previous versions of the container. `copyContainer` allows developers to generate a new detached container from another container.
|
||||
|
||||
[`getContainerVersions(id, options)`]({{< relref "azureclient-class.md#getcontainerversions-method" >}})
|
||||
[copyContainer(id, containerSchema)]({{< relref "azureclient-class.md#copycontainer-method" >}})
|
||||
[`getContainerVersions(id, options)`]({{< apiref "azure-client" "AzureClient" "class" "v1" >}}#getcontainerversions-method)
|
||||
[copyContainer(id, containerSchema)]({{< apiref "azure-client" "AzureClient" "class" "v1" >}}#copycontainer-method)
|
||||
|
||||
In an situation where a container will fail to load these two methods can be used together to load a document from a previous state in time.
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
images:
|
||||
- image: images/wallpaperflare.com_wallpaper (1).jpg
|
||||
content_html: "1"
|
||||
- image: images/wallpaperflare.com_wallpaper (3).jpg
|
||||
content_html: "2"
|
||||
- image: images/wallpaperflare.com_wallpaper.jpg
|
||||
content_html: "3"
|
||||
- image: images/wallpaperflare.com_wallpaper (3).jpg
|
||||
content_html: "4"
|
|
@ -1,12 +1,13 @@
|
|||
{
|
||||
"params": {
|
||||
"currentVersion": "v1",
|
||||
"currentVersion": "v2",
|
||||
"ltsVersion": "v1",
|
||||
"previousVersions": [],
|
||||
"previousVersions": ["v1"],
|
||||
"downloadVersions": ["v1"]
|
||||
},
|
||||
"apiDocsDirectory": "/docs/api/",
|
||||
"apiVersionOptionName": {
|
||||
"Fluid Framework 1.0": "v1"
|
||||
"Fluid Framework 1.0": "v1",
|
||||
"Fluid Framework 2.0 (BETA)": "v2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
{{/* Helper template for linking to an API member's generated docs. */}}
|
||||
{{/* Parameters: */}}
|
||||
{{/* - unscopedPackageName: The *unscoped* name of the package to which the API member belongs. */}}
|
||||
{{/* - name: The API member name. Note that this must be an item for which a document is rendered. */}}
|
||||
{{/* This includes classes, interfaces, and namespaces. */}}
|
||||
{{/* - kind: The kind of API item (must be "class", "interface", or "namespace"). */}}
|
||||
{{/* - (optional) unscopedPackageName: The *unscoped* name of the package to which the API member belongs. */}}
|
||||
{{/* default value: "fluid-framework" */}}
|
||||
{{/* - (optional) version: The specific API docs version to point to. Default is the site's "current version". E.g. "v1" or "v2". */}}
|
||||
|
||||
{{- $name := .Get 0 -}}
|
||||
{{- $kind := .Get 1 -}}
|
||||
{{- $unscopedPackageName := default "fluid-framework" (.Get 2) -}}
|
||||
{{- $unscopedPackageName := .Get 0 -}}
|
||||
{{- $name := .Get 1 -}}
|
||||
{{- $kind := .Get 2 -}}
|
||||
{{- $version := default $.Site.Data.params.versions.currentVersion (.Get 3) -}}
|
||||
|
||||
{{- $fileNameWithoutExtension := lower (delimit (slice $name $kind) "-") -}}
|
||||
{{- $fileName := delimit (slice $fileNameWithoutExtension ".md") "" -}}
|
||||
{{- $currentVersion := $.Site.Data.versions.currentVersion -}}
|
||||
{{- $apiLink := print "/docs/api/" $currentVersion "/" -}}
|
||||
|
||||
{{- $apiLink := print "/docs/api/" $version "/" -}}
|
||||
{{- $path := delimit (slice $apiLink $unscopedPackageName "/" $fileName) "" -}}
|
||||
|
||||
<a href="{{ relref . $path }}"><code>{{ $name }}</code></a>
|
||||
{{ relref . $path }}
|
||||
|
||||
{{- /* Strip trailing newline. */ -}}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
{{ .Scratch.Set "height" (.Get "height") }}
|
||||
{{ .Scratch.Set "unit" (.Get "unit") }}
|
||||
{{ .Scratch.Set "ordinal" .Ordinal }}
|
||||
{{ .Scratch.Set "items" (.Get "items") }}
|
||||
<div id="carousel{{ .Ordinal }}" class="carousel" duration="{{ .Get `duration` }}">
|
||||
<ul>
|
||||
{{ range $index, $slide := .Site.Data.carousel.images }}
|
||||
<li id="c{{ $.Scratch.Get "ordinal" }}_slide{{ add $index 1}}" style="min-width: calc(100%/{{ $.Scratch.Get "items" }}); padding-bottom: {{ $.Scratch.Get "height" }}{{ $.Scratch.Get "unit" }};">
|
||||
<img src="{{ $slide.image }}" alt="" />
|
||||
<div><div>{{ $slide.content_html }}</div></div>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<ol>
|
||||
{{ range $index, $page := .Site.Data.carousel.images }}
|
||||
<li><a href="#c{{ $.Scratch.Get "ordinal" }}_slide{{ add $index 1 }}"></a></li>
|
||||
{{ end }}
|
||||
</ol>
|
||||
<div class="prev">‹</div>
|
||||
<div class="next">›</div>
|
||||
</div>
|
|
@ -1,7 +1,7 @@
|
|||
{{ $idPrefix := .Get "idPrefix" }}
|
||||
{{ $bundleName := .Get "bundleName" }}
|
||||
|
||||
<div id="content" style="min-height: 200px; display: flex;">
|
||||
<div id="content" style="min-height: 200px;">
|
||||
<div class="browser-window-wrapper">
|
||||
<div aria-hidden="true" class="browser-window">
|
||||
<div class="browser-window-nav">
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
.browser-window-wrapper {
|
||||
flex-grow: 1;
|
||||
width: 50%;
|
||||
width: 100%;
|
||||
border: 1px solid lightgray;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
{{/* Helper template for linking to the root page of a package's API docs. */}}
|
||||
{{/* Parameters: */}}
|
||||
{{/* - unscopedPackageName: The *unscoped* name of the package being linked to. */}}
|
||||
{{/* - (optional) version: The specific API docs version to point to. Default is the site's "current version". E.g. "v1" or "v2". */}}
|
||||
|
||||
{{- $currentVersion := $.Site.Data.versions.currentVersion -}}
|
||||
{{- $apiLink := print "/docs/api/" $currentVersion "/" -}}
|
||||
{{- $unscopedPackageName := .Get 0 -}}
|
||||
{{- $path := delimit (slice $apiLink $unscopedPackageName ".md" ) "" -}}
|
||||
{{- $version := default $.Site.Data.versions.params.currentVersion (.Get 1) -}}
|
||||
|
||||
<a href="{{ relref . $path }}"><code>{{ $unscopedPackageName }}</code></a>
|
||||
{{- $path := delimit (slice "/docs/api/" $version "/" $unscopedPackageName ".md" ) "" -}}
|
||||
|
||||
{{ relref . $path }}
|
||||
|
||||
{{- /* Strip trailing newline. */ -}}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
<svg id="emoji" viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="color">
|
||||
<polygon fill="#FCEA2B" stroke="none" points="53,32.2969 54.875,32.2969 54.875,59.1719 16.875,59.1719 16.875,32.2969 18.75,32.2969"/>
|
||||
<polygon fill="#F1B31C" stroke="none" points="54.4302,32.493 35.66,58.9944 54.9675,58.9944"/>
|
||||
<path fill="#D0CFCE" stroke="#D0CFCE" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" d="M46.0641,31.8167 l0.2102-2.902c0.4766-6.9852-4.8299-12.6829-10.5142-12.4934c-4.6725,0.1558-8.6157,4.2846-9.8282,9.301l-4.0503-0.9026 c1.6615-6.6916,7.2189-12.2207,13.8118-12.4281c7.9697-0.2507,15.4098,7.2847,14.7416,16.523l-0.2425,2.902"/>
|
||||
</g>
|
||||
<g id="hair"/>
|
||||
<g id="skin"/>
|
||||
<g id="skin-shadow"/>
|
||||
<g id="line">
|
||||
<polygon fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" points="53,32.25 54.875,32.25 54.875,59.125 16.875,59.125 16.875,32.25 18.75,32.25"/>
|
||||
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" d="M46.2743,28.9146c0.4766-6.9852-4.8299-12.6829-10.5142-12.4934c-4.6725,0.1558-8.6157,4.2846-9.8282,9.301l-4.0503-0.9026 c1.6615-6.6916,7.2189-12.2207,13.8118-12.4281c7.9697-0.2507,15.4098,7.2847,14.7416,16.523"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.3 KiB |
|
@ -0,0 +1,20 @@
|
|||
<svg id="emoji" viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="color">
|
||||
<circle cx="48.4645" cy="23.7594" r="2.1014" fill="#fff"/>
|
||||
<path fill="#fcea2b" d="m16.12,48.114c-3.1584,3.1634-4.6518,7.5601-3.97,11.688,4.128.6763,8.5223-.8196,11.683-3.977,3.1584-3.1634,4.6518-7.5601,3.97-11.688-4.128-.6763-8.5223.8196-11.683,3.977Z"/>
|
||||
<path fill="#61b2e4" d="m31.973,45.839c-.1919.966-.6657,1.8536-1.3616,2.5507-.3389.3373-.7246.6241-1.1452.8516,2.1626,2.9716,3.7579,6.2847,4.6952,9.7506.7092-.6216,1.3906-1.2786,2.0417-1.9685,1.9136-2.0343,3.5491-4.3376,4.8516-6.8326,1.2507-2.4201,2.1751-4.9922,2.7442-7.6354-3.7285,1.9544-7.7719,3.0771-11.826,3.2837h0Z"/>
|
||||
<path fill="#92d3f5" d="m14.923,35.749c-.69.65-1.3472,1.3303-1.9691,2.0383,3.4682.9313,6.7846,2.521,9.7604,4.6784.2264-.414.5104-.7939.8435-1.1281.6949-.6935,1.5791-1.1665,2.5417-1.3598.2106-4.0507,1.3364-8.0899,3.293-11.814.0019-.0037.0037-.0074.0056-.0112-2.645.5687-5.2188,1.4928-7.6405,2.7434-2.496,1.303-4.7999,2.9389-6.8346,4.853h0Z"/>
|
||||
<path fill="#ea5a47" d="m34.821,20.747c-5.2314,5.2507-8.3665,12.1635-8.7228,19.233,1.6376-.3318,3.3326.1781,4.515,1.3584,1.186,1.1868,1.6956,2.8903,1.356,4.5332,7.0754-.3609,13.9919-3.5024,19.242-8.7398,6.7117-6.7229,9.8843-16.067,8.4337-24.839-1.7318-.2827-3.5044-.3879-5.2915-.3141-7.1741.2926-14.2097,3.4508-19.532,8.7677l-.0004.0006Zm10.249-.5291c1.8412-1.8413,4.8269-1.8418,6.6687-.0012.0004.0004.0008.0008.0012.0012,1.8418,1.8407,1.8424,4.8255.0012,6.6667-.0004.0004-.0008.0008-.0012.0012-1.8419,1.8404-4.8274,1.8398-6.6685-.0014-1.8417-1.8406-1.8424-4.8252-.0014-6.6665Z"/>
|
||||
<path fill="#f1b31c" d="m26.538,52.037c-.8756.9831-1.8894,1.8467-3.0072,2.5617-3.4907,2.2228-7.7244,2.8345-11.441,1.653-.1495,1.1964-.1293,2.3916.06,3.5496,4.128.6763,8.5223-.8195,11.683-3.9769,1.1048-1.1131,2.0209-2.3956,2.7055-3.7874h-.0003Z"/>
|
||||
<path fill="#d22f27" d="m26.204,38.687c-.033.4281-.0559.8558-.0684,1.283,1.6271-.316,3.305.1967,4.4773,1.3682,1.186,1.1868,1.6956,2.8903,1.356,4.5332,7.075-.3618,13.9907-3.5038,19.24-8.7412,1.4932-1.5067,2.8266-3.1619,3.9746-4.9339-1.3472,1.2267-2.8051,2.3344-4.353,3.3074-7.5574,4.7109-16.6938,5.8918-24.627,3.1832h.0005Z"/>
|
||||
<path fill="#61b2e4" d="m24.039,48.551c.8703-.4372,1.7206-.9178,2.5501-1.438,2.4433-1.5323,4.6776-3.4046,6.6294-5.5552l.0028-.0028c1.8803-2.0911,3.4745-4.4187,4.7329-6.9122.061-.1204.0967-.252.1047-.3867-3.3985-.7533-14.846,10.251-14.0199,14.2949h0Z"/>
|
||||
</g>
|
||||
<g id="line">
|
||||
<path d="m48.405,29.49c-3.2761,0-5.941-2.6641-5.941-5.9392s2.6649-5.9392,5.941-5.9392,5.941,2.6641,5.941,5.9392-2.6649,5.9392-5.941,5.9392Zm0-9.8987c-2.1839,0-3.9607,1.7757-3.9607,3.9595s1.7768,3.9595,3.9607,3.9595,3.9607-1.7758,3.9607-3.9595-1.7769-3.9595-3.9607-3.9595Z"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.949" d="m20.653,45.063c-1.678.7083-3.2222,1.7475-4.5331,3.0508-3.1581,3.1631-4.6517,7.5594-3.9703,11.687,4.128.6762,8.5221-.8196,11.683-3.9769,1.3043-1.3104,2.3446-2.8541,3.0537-4.5318"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.949" d="m14.923,35.749c-.69.65-1.3472,1.3303-1.9691,2.0383,3.4682.9313,6.7846,2.521,9.7604,4.6784.2264-.414.5104-.7939.8435-1.1281.6949-.6935,1.5791-1.1665,2.5417-1.3598.2106-4.0507,1.3364-8.0899,3.293-11.814.0019-.0037.0037-.0074.0056-.0112-2.645.5687-5.2188,1.4928-7.6405,2.7434-2.496,1.303-4.7999,2.9389-6.8346,4.853h0Z"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.949" d="m31.973,45.839c-.1919.966-.6657,1.8536-1.3616,2.5507-.3389.3373-.7246.6241-1.1452.8516,2.1626,2.9716,3.7579,6.2847,4.6952,9.7506.7092-.6216,1.3906-1.2786,2.0417-1.9685,1.9136-2.0343,3.5491-4.3376,4.8516-6.8326,1.2507-2.4201,2.1751-4.9922,2.7442-7.6354-3.7285,1.9544-7.7719,3.0771-11.826,3.2837h0Z"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.949" d="m31.83,43.345c.2696.8863.2506,1.6919.1371,2.5245,7.0759-.3611,13.993-3.5031,19.243-8.7412,6.7106-6.7215,9.8836-16.063,8.4351-24.834-8.7712-1.4365-18.108,1.742-24.823,8.4508-5.2322,5.2509-8.3679,12.164-8.7242,19.234.9413-.1907,1.8984-.0942,2.7693.2387"/>
|
||||
<path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.949" d="m37.072,34.196h-.0002c-2.4156,1.2183-4.6724,2.7626-6.6996,4.5844-2.0849,1.8911-3.9,4.0556-5.3844,6.4211-.5039.8031-.9684,1.6273-1.3917,2.4694"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 4.4 KiB |
|
@ -0,0 +1,29 @@
|
|||
<svg id="emoji" viewBox="0 0 72 72" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="color">
|
||||
<path fill="#92D3F5" d="M17.2831,58.8244c0,0-2-13.5,10-13.5c3.1918,2.1279,5.9264,3.5984,9,3.5921h-0.125 c3.0736,0.0063,4.7081-2.1642,7.9-4.2921c15.5705-0.0001,11.5,14.2,11.5,14.2"/>
|
||||
<polygon fill="#FFFFFF" points="35.5372,55.498 32.2983,51.5662 29.0593,47.6344 35.5372,47.6344 42.0152,47.6344 38.7762,51.5662"/>
|
||||
<path fill="#61B2E4" d="M26.5302,44.9199c0,0-5.9003,4.0266-2.161,7.4669h4.5729l-0.8335,3.7419l7.8919,1.9525l0.2903-2.5055 l-8.3606-10.3636"/>
|
||||
<polygon fill="#D0CFCE" points="67.0867,43.4225 60.1367,59.7725 35.1467,59.7725 42.0967,43.4225"/>
|
||||
<polygon fill="#9B9B9A" points="67.3033,43.4225 60.3533,59.7725 60.1333,59.7725 51.3633,59.7725 58.3133,43.4225 67.0833,43.4225"/>
|
||||
</g>
|
||||
<g id="hair">
|
||||
<path fill="#A57939" d="M26,36.5808c-4,0-4-6-4-13s4-14,14-14s14,7,14,14s0,13-4,13"/>
|
||||
</g>
|
||||
<g id="skin">
|
||||
<path fill="#FCEA2B" d="M24.9365,28.5808c0,9,4.9365,14,11,14c5.9365,0,11.0635-5,11.0635-14c0.0245-1.7187-0.3164-3.4229-1-5 c-3-3-7-8-7-8c-4,3-7,6-13,7.0005C26,22.5808,24.9365,23.58,24.9365,28.5808z"/>
|
||||
</g>
|
||||
<g id="skin-shadow"/>
|
||||
<g id="line">
|
||||
<path d="M16.917,58.9189c-0.4844,0.001-0.9102-0.3525-0.9863-0.8466c-0.0411-0.2696-0.9727-6.6328,2.581-10.7754 c1.9229-2.2412,4.751-3.377,8.4072-3.377c0.1973,0,0.3907,0.0586,0.5547,0.168c3.1631,2.1084,5.6758,3.418,8.4053,3.4238h0.04 c0.5518,0,0.9991,0.4473,1,0.999c0.001,0.5518-0.4462,1-0.998,1.001c-0.001,0-0.001,0-0.002,0H35.916 c-0.0107-0.001-0.0254-0.001-0.0381,0h-0.084c-0.0146,0-0.0302,0-0.0449-0.001c-3.0986-0.0419-5.8164-1.4023-9.1269-3.5878 c-2.8965,0.0566-5.1104,0.9541-6.586,2.6689c-2.956,3.4365-2.1377,9.1201-2.1289,9.1777c0.083,0.545-0.292,1.0547-0.8379,1.1387 C17.0186,58.916,16.9678,58.9189,16.917,58.9189z"/>
|
||||
<path d="M33.9961,55.2832c-0.294,0-0.584-0.1279-0.7813-0.375l-7.2646-9.0713c-0.3457-0.4306-0.2764-1.0605,0.1553-1.4053 c0.4326-0.3486,1.0615-0.2753,1.4052,0.1553l7.2647,9.0713c0.3457,0.4307,0.2764,1.0606-0.1553,1.4053 C34.4355,55.2119,34.2148,55.2832,33.9961,55.2832z"/>
|
||||
<path d="M33.0068,57.3555c-0.0742,0-0.1494-0.0078-0.2255-0.0254l-4.8975-1.127c-0.2686-0.0615-0.499-0.2314-0.6387-0.4697 c-0.1387-0.2373-0.1738-0.5225-0.0967-0.7861l0.458-1.5606h-3.2373c-0.2509,0-0.4921-0.0947-0.6767-0.2637 c-1.4043-1.2919-1.6201-2.6455-1.5537-3.5546c0.2129-2.9268,3.459-5.2227,3.8281-5.4746c0.4551-0.3116,1.0762-0.1934,1.3877,0.2617 c0.3115,0.455,0.1953,1.0771-0.2598,1.3896c-0.7832,0.5381-2.8427,2.3008-2.9619,3.9717c-0.042,0.5918,0.1709,1.1406,0.6504,1.6699 h4.1592c0.3154,0,0.6113,0.1485,0.8008,0.4004c0.1884,0.2529,0.247,0.5791,0.1591,0.8809l-0.5351,1.8242l3.8633,0.8887 c0.5381,0.124,0.874,0.6601,0.75,1.1992C33.874,57.042,33.4619,57.3555,33.0068,57.3555z"/>
|
||||
<polygon fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" points="35.1467,59.7725 60.1367,59.7725 67.0867,43.4225 42.0967,43.4225"/>
|
||||
<line x1="24.1767" x2="35.1467" y1="59.7725" y2="59.7725" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<path d="M41.9529,27.0468c0,1.1046-0.8954,2-2,2s-2-0.8954-2-2s0.8954-2,2-2C41.0573,25.0472,41.9525,25.9424,41.9529,27.0468"/>
|
||||
<path d="M33.9529,27.0468c0,1.1046-0.8954,2-2,2s-2-0.8954-2-2s0.8954-2,2-2C33.0573,25.0472,33.9525,25.9424,33.9529,27.0468"/>
|
||||
<path d="M35.9527,37.0492c-1.2005-0.0116-2.3813-0.3055-3.4472-0.8579c-0.494-0.247-0.6943-0.8477-0.4473-1.3418 c0.247-0.4941,0.8477-0.6943,1.3418-0.4473c1.5934,0.8593,3.5121,0.8593,5.1055,0c0.494-0.247,1.0947-0.0468,1.3418,0.4473 s0.0468,1.0947-0.4473,1.3418C38.3341,36.7437,37.1532,37.0376,35.9527,37.0492z"/>
|
||||
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M26,36.5808c-4,0-4-6-4-13 s4-14,14-14s14,7,14,14s0,13-4,13"/>
|
||||
<path fill="none" stroke="#000000" stroke-linejoin="round" stroke-width="2" d="M24.9365,28.5808c0,9,4.9365,14,11,14 c5.9365,0,11.0635-5,11.0635-14c0.0245-1.7187-0.3164-3.4229-1-5c-3-3-7-8-7-8c-4,3-7,6-13,7.0005 C26,22.5808,24.9365,23.58,24.9365,28.5808z"/>
|
||||
<path d="M41.4707,32.668h-2.0078c-1.5479,0-2.8828-0.9258-3.4815-2.253c-0.5976,1.3272-1.9335,2.253-3.4804,2.253h-2.0078 c-2.1045,0-3.8164-1.7119-3.8164-3.8164v-1.2378h-0.6924c-0.5528,0-1-0.4478-1-1c0-0.5523,0.4472-1,1-1h1.6924 c0.5527,0,1,0.4477,1,1v2.2378c0,1.0019,0.8144,1.8164,1.8164,1.8164h2.0078c1.001,0,1.8154-0.8145,1.8154-1.8164v-1.104 c0-0.5523,0.4473-1,1-1h1.3301c0.5527,0,1,0.4477,1,1v1.104c0,1.0019,0.8144,1.8164,1.8164,1.8164h2.0078 c1.001,0,1.8154-0.8145,1.8154-1.8164v-2.2378c0-0.5523,0.4473-1,1-1h1.1573c0.5527,0,1,0.4477,1,1c0,0.5522-0.4473,1-1,1h-0.1573 v1.2378C45.2861,30.9561,43.5742,32.668,41.4707,32.668z"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 4.7 KiB |
После Ширина: | Высота: | Размер: 4.9 KiB |
После Ширина: | Высота: | Размер: 598 KiB |
|
@ -0,0 +1,17 @@
|
|||
<svg id="emoji" viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="color">
|
||||
<rect x="11" y="16.0833" width="50" height="39.8333" fill="#d0cfce" stroke="none"/>
|
||||
</g>
|
||||
<g id="hair"/>
|
||||
<g id="skin"/>
|
||||
<g id="skin-shadow"/>
|
||||
<g id="line">
|
||||
<rect x="11" y="16.0009" width="50" height="39.9982" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<polyline fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" points="16.3287,16.4792 16.3287,20.8542 11,20.8542 61,20.8542"/>
|
||||
<line x1="28.8333" x2="21.9062" y1="30.3947" y2="37.3218" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<line x1="28.8333" x2="21.9062" y1="44.3166" y2="37.3895" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<line x1="38.1836" x2="32.8086" y1="28.1523" y2="46.25" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<line x1="42.1588" x2="49.0859" y1="44.2515" y2="37.3244" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<line x1="42.1588" x2="49.0859" y1="30.3296" y2="37.2567" fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.5 KiB |
После Ширина: | Высота: | Размер: 20 KiB |
После Ширина: | Высота: | Размер: 69 KiB |
После Ширина: | Высота: | Размер: 7.0 KiB |
После Ширина: | Высота: | Размер: 22 KiB |
После Ширина: | Высота: | Размер: 69 KiB |
После Ширина: | Высота: | Размер: 125 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 64 64"><defs><linearGradient id="a" x1="20.248" y1="3.476" x2="37.161" y2="32.769" gradientUnits="userSpaceOnUse"><stop offset="0.06" stop-color="#04868c"/><stop offset="0.942" stop-color="#025b5e"/></linearGradient><linearGradient id="b" x1="39.749" y1="22.074" x2="55.251" y2="48.926" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#18949a"/><stop offset="0.466" stop-color="#14858c"/><stop offset="1" stop-color="#117880"/></linearGradient><linearGradient id="c" x1="26.249" y1="38.673" x2="38.751" y2="60.327" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2dbcc8"/><stop offset="1" stop-color="#24b2c0"/></linearGradient><linearGradient id="d" x1="5.56" y1="13.917" x2="26.44" y2="50.083" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#058f92"/><stop offset="0.5" stop-color="#038489"/><stop offset="1" stop-color="#026d71"/></linearGradient></defs><title>SharePoint_64x</title><circle cx="29.5" cy="19.5" r="18.5" fill="url(#a)"/><circle cx="47.5" cy="35.5" r="15.5" fill="url(#b)"/><circle cx="32.5" cy="49.5" r="12.5" fill="url(#c)"/><rect width="64" height="64" fill="none"/><path d="M30.306,16H11.341A18.456,18.456,0,0,0,27.818,37.915,12.4,12.4,0,0,0,20.1,51H30.306a2.643,2.643,0,0,0,2.628-2.179,1.921,1.921,0,0,0,.046-.452V18.631A2.648,2.648,0,0,0,30.306,16Z" opacity="0.2"/><path d="M30.2,15H11.574A18.422,18.422,0,0,0,27.818,37.915,12.5,12.5,0,0,0,20,49.5c0,.169.018.333.025.5H30.2a3.793,3.793,0,0,0,2.61-1.05A3.7,3.7,0,0,0,34,46.24V18.76A3.791,3.791,0,0,0,30.2,15Z" opacity="0.1"/><path d="M30.306,16H11.341A18.456,18.456,0,0,0,27.818,37.915,12.5,12.5,0,0,0,20.019,49H30.306a2.658,2.658,0,0,0,2.674-2.651v-27.7A2.658,2.658,0,0,0,30.306,16Z" opacity="0.2"/><path d="M29.266,16H11.341A18.456,18.456,0,0,0,27.818,37.915,12.5,12.5,0,0,0,20.019,49h9.247a2.669,2.669,0,0,0,2.694-2.651v-27.7A2.669,2.669,0,0,0,29.266,16Z" opacity="0.1"/><rect y="16" width="32" height="32" rx="2.667" fill="url(#d)"/><path d="M11.679,31.675a4.914,4.914,0,0,1-1.526-1.613,4.384,4.384,0,0,1-.531-2.207A4.246,4.246,0,0,1,10.61,25a5.828,5.828,0,0,1,2.626-1.713,11.1,11.1,0,0,1,3.589-.557,13.635,13.635,0,0,1,4.728.663v3.339a7.391,7.391,0,0,0-2.139-.875,10.329,10.329,0,0,0-2.5-.3,5.427,5.427,0,0,0-2.57.544,1.688,1.688,0,0,0-1.019,1.545,1.561,1.561,0,0,0,.431,1.094,3.932,3.932,0,0,0,1.163.832q.732.363,2.183.963a2.239,2.239,0,0,1,.312.125,18.032,18.032,0,0,1,2.752,1.357,4.937,4.937,0,0,1,1.625,1.638,4.742,4.742,0,0,1,.588,2.47,4.6,4.6,0,0,1-.925,2.977,5.175,5.175,0,0,1-2.477,1.663,11.2,11.2,0,0,1-3.526.513,18.619,18.619,0,0,1-3.2-.263,10.99,10.99,0,0,1-2.595-.75V36.734a8.374,8.374,0,0,0,2.627,1.251,10.244,10.244,0,0,0,2.889.462,4.972,4.972,0,0,0,2.62-.556,1.758,1.758,0,0,0,.881-1.57,1.672,1.672,0,0,0-.494-1.2,4.99,4.99,0,0,0-1.363-.951q-.869-.438-2.57-1.15A14.612,14.612,0,0,1,11.679,31.675Z" fill="#fff"/></svg>
|
После Ширина: | Высота: | Размер: 2.9 KiB |
После Ширина: | Высота: | Размер: 2.3 KiB |
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2228.833 2073.333">
|
||||
<path fill="#5059C9" d="M1554.637,777.5h575.713c54.391,0,98.483,44.092,98.483,98.483c0,0,0,0,0,0v524.398 c0,199.901-162.051,361.952-361.952,361.952h0h-1.711c-199.901,0.028-361.975-162-362.004-361.901c0-0.017,0-0.034,0-0.052V828.971 C1503.167,800.544,1526.211,777.5,1554.637,777.5L1554.637,777.5z"/>
|
||||
<circle fill="#5059C9" cx="1943.75" cy="440.583" r="233.25"/>
|
||||
<circle fill="#7B83EB" cx="1218.083" cy="336.917" r="336.917"/>
|
||||
<path fill="#7B83EB" d="M1667.323,777.5H717.01c-53.743,1.33-96.257,45.931-95.01,99.676v598.105 c-7.505,322.519,247.657,590.16,570.167,598.053c322.51-7.893,577.671-275.534,570.167-598.053V877.176 C1763.579,823.431,1721.066,778.83,1667.323,777.5z"/>
|
||||
<path opacity=".1" d="M1244,777.5v838.145c-0.258,38.435-23.549,72.964-59.09,87.598 c-11.316,4.787-23.478,7.254-35.765,7.257H667.613c-6.738-17.105-12.958-34.21-18.142-51.833 c-18.144-59.477-27.402-121.307-27.472-183.49V877.02c-1.246-53.659,41.198-98.19,94.855-99.52H1244z"/>
|
||||
<path opacity=".2" d="M1192.167,777.5v889.978c-0.002,12.287-2.47,24.449-7.257,35.765 c-14.634,35.541-49.163,58.833-87.598,59.09H691.975c-8.812-17.105-17.105-34.21-24.362-51.833 c-7.257-17.623-12.958-34.21-18.142-51.833c-18.144-59.476-27.402-121.307-27.472-183.49V877.02 c-1.246-53.659,41.198-98.19,94.855-99.52H1192.167z"/>
|
||||
<path opacity=".2" d="M1192.167,777.5v786.312c-0.395,52.223-42.632,94.46-94.855,94.855h-447.84 c-18.144-59.476-27.402-121.307-27.472-183.49V877.02c-1.246-53.659,41.198-98.19,94.855-99.52H1192.167z"/>
|
||||
<path opacity=".2" d="M1140.333,777.5v786.312c-0.395,52.223-42.632,94.46-94.855,94.855H649.472 c-18.144-59.476-27.402-121.307-27.472-183.49V877.02c-1.246-53.659,41.198-98.19,94.855-99.52H1140.333z"/>
|
||||
<path opacity=".1" d="M1244,509.522v163.275c-8.812,0.518-17.105,1.037-25.917,1.037 c-8.812,0-17.105-0.518-25.917-1.037c-17.496-1.161-34.848-3.937-51.833-8.293c-104.963-24.857-191.679-98.469-233.25-198.003 c-7.153-16.715-12.706-34.071-16.587-51.833h258.648C1201.449,414.866,1243.801,457.217,1244,509.522z"/>
|
||||
<path opacity=".2" d="M1192.167,561.355v111.442c-17.496-1.161-34.848-3.937-51.833-8.293 c-104.963-24.857-191.679-98.469-233.25-198.003h190.228C1149.616,466.699,1191.968,509.051,1192.167,561.355z"/>
|
||||
<path opacity=".2" d="M1192.167,561.355v111.442c-17.496-1.161-34.848-3.937-51.833-8.293 c-104.963-24.857-191.679-98.469-233.25-198.003h190.228C1149.616,466.699,1191.968,509.051,1192.167,561.355z"/>
|
||||
<path opacity=".2" d="M1140.333,561.355v103.148c-104.963-24.857-191.679-98.469-233.25-198.003 h138.395C1097.783,466.699,1140.134,509.051,1140.333,561.355z"/>
|
||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="198.099" y1="1683.0726" x2="942.2344" y2="394.2607" gradientTransform="matrix(1 0 0 -1 0 2075.3333)">
|
||||
<stop offset="0" stop-color="#5a62c3"/>
|
||||
<stop offset=".5" stop-color="#4d55bd"/>
|
||||
<stop offset="1" stop-color="#3940ab"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#a)" d="M95.01,466.5h950.312c52.473,0,95.01,42.538,95.01,95.01v950.312c0,52.473-42.538,95.01-95.01,95.01 H95.01c-52.473,0-95.01-42.538-95.01-95.01V561.51C0,509.038,42.538,466.5,95.01,466.5z"/>
|
||||
<path fill="#FFF" d="M820.211,828.193H630.241v517.297H509.211V828.193H320.123V727.844h500.088V828.193z"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.2 KiB |
После Ширина: | Высота: | Размер: 266 KiB |
|
@ -0,0 +1,23 @@
|
|||
<svg width="150" height="150" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="e399c19f-b68f-429d-b176-18c2117ff73c" x1="-1032.172" x2="-1059.213" y1="145.312" y2="65.426" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#114a8b"></stop>
|
||||
<stop offset="1" stop-color="#0669bc"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15" x1="-1023.725" x2="-1029.98" y1="108.083" y2="105.968" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-opacity=".3"></stop>
|
||||
<stop offset=".071" stop-opacity=".2"></stop>
|
||||
<stop offset=".321" stop-opacity=".1"></stop>
|
||||
<stop offset=".623" stop-opacity=".05"></stop>
|
||||
<stop offset="1" stop-opacity="0"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient id="a7fee970-a784-4bb1-af8d-63d18e5f7db9" x1="-1027.165" x2="-997.482" y1="147.642" y2="68.561" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#3ccbf4"></stop>
|
||||
<stop offset="1" stop-color="#2892df"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path fill="url(#e399c19f-b68f-429d-b176-18c2117ff73c)" d="M33.338 6.544h26.038l-27.03 80.087a4.152 4.152 0 0 1-3.933 2.824H8.149a4.145 4.145 0 0 1-3.928-5.47L29.404 9.368a4.152 4.152 0 0 1 3.934-2.825z"></path>
|
||||
<path fill="#0078d4" d="M71.175 60.261h-41.29a1.911 1.911 0 0 0-1.305 3.309l26.532 24.764a4.171 4.171 0 0 0 2.846 1.121h23.38z"></path>
|
||||
<path fill="url(#ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15)" d="M33.338 6.544a4.118 4.118 0 0 0-3.943 2.879L4.252 83.917a4.14 4.14 0 0 0 3.908 5.538h20.787a4.443 4.443 0 0 0 3.41-2.9l5.014-14.777 17.91 16.705a4.237 4.237 0 0 0 2.666.972H81.24L71.024 60.261l-29.781.007L59.47 6.544z"></path>
|
||||
<path fill="url(#a7fee970-a784-4bb1-af8d-63d18e5f7db9)" d="M66.595 9.364a4.145 4.145 0 0 0-3.928-2.82H33.648a4.146 4.146 0 0 1 3.928 2.82l25.184 74.62a4.146 4.146 0 0 1-3.928 5.472h29.02a4.146 4.146 0 0 0 3.927-5.472z"></path>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.1 KiB |
До Ширина: | Высота: | Размер: 106 KiB После Ширина: | Высота: | Размер: 154 KiB |
После Ширина: | Высота: | Размер: 90 KiB |
После Ширина: | Высота: | Размер: 79 KiB |
|
@ -0,0 +1 @@
|
|||
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>
|
После Ширина: | Высота: | Размер: 963 B |
После Ширина: | Высота: | Размер: 76 KiB |
После Ширина: | Высота: | Размер: 13 KiB |
После Ширина: | Высота: | Размер: 29 KiB |
После Ширина: | Высота: | Размер: 94 KiB |
После Ширина: | Высота: | Размер: 108 KiB |
После Ширина: | Высота: | Размер: 62 KiB |
После Ширина: | Высота: | Размер: 85 KiB |
После Ширина: | Высота: | Размер: 91 KiB |
После Ширина: | Высота: | Размер: 7.5 KiB |
После Ширина: | Высота: | Размер: 17 KiB |
|
@ -0,0 +1,17 @@
|
|||
<svg width="206" height="104" viewBox="0 0 206 104" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M25.1875 0C26.7663 0 28.2881 0.203451 29.7529 0.610352C31.2178 1.01725 32.585 1.59505 33.8545 2.34375C35.1403 3.09245 36.304 3.98763 37.3457 5.0293C38.3874 6.07096 39.2826 7.2347 40.0312 8.52051C40.7799 9.79004 41.3577 11.1572 41.7646 12.6221C42.1716 14.0869 42.375 15.6087 42.375 17.1875C42.375 19.5475 41.9274 21.7367 41.0322 23.7549C40.137 25.7731 38.8594 27.6042 37.1992 29.248C35.8483 30.5827 34.8066 32.0719 34.0742 33.7158C33.3581 35.3597 33 37.1419 33 39.0625V45.3125C33 45.9635 32.8779 46.5739 32.6338 47.1436C32.3896 47.7132 32.056 48.2096 31.6328 48.6328C31.2096 49.056 30.7132 49.3896 30.1436 49.6338C29.5739 49.8779 28.9635 50 28.3125 50H22.0625C21.4115 50 20.8011 49.8779 20.2314 49.6338C19.6618 49.3896 19.1654 49.056 18.7422 48.6328C18.319 48.2096 17.9854 47.7132 17.7412 47.1436C17.4971 46.5739 17.375 45.9635 17.375 45.3125V39.0625C17.375 37.1419 17.0088 35.3597 16.2764 33.7158C15.5602 32.0719 14.5267 30.5827 13.1758 29.248C11.5156 27.6042 10.238 25.7731 9.34277 23.7549C8.44759 21.7367 8 19.5475 8 17.1875C8 15.6087 8.20345 14.0869 8.61035 12.6221C9.01725 11.1572 9.59505 9.79004 10.3438 8.52051C11.0924 7.2347 11.9876 6.07096 13.0293 5.0293C14.071 3.98763 15.2266 3.09245 16.4961 2.34375C17.7819 1.59505 19.1572 1.01725 20.6221 0.610352C22.0869 0.203451 23.6087 0 25.1875 0ZM28.3125 46.875C28.7357 46.875 29.1019 46.7204 29.4111 46.4111C29.7204 46.1019 29.875 45.7357 29.875 45.3125V40.625H20.5V45.3125C20.5 45.7357 20.6546 46.1019 20.9639 46.4111C21.2731 46.7204 21.6393 46.875 22.0625 46.875H28.3125ZM29.9482 37.5C30.1598 35.4004 30.6969 33.4961 31.5596 31.7871C32.4222 30.0781 33.5859 28.4831 35.0508 27.002C36.4017 25.6348 37.4352 24.1455 38.1514 22.5342C38.8838 20.9066 39.25 19.1243 39.25 17.1875C39.25 15.2507 38.8757 13.4277 38.127 11.7188C37.3945 10.0098 36.3936 8.52051 35.124 7.25098C33.8545 5.98145 32.3652 4.98047 30.6562 4.24805C28.9473 3.49935 27.1243 3.125 25.1875 3.125C23.2507 3.125 21.4277 3.49935 19.7188 4.24805C18.0098 4.98047 16.5205 5.98145 15.251 7.25098C13.9814 8.52051 12.9723 10.0098 12.2236 11.7188C11.4912 13.4277 11.125 15.2507 11.125 17.1875C11.125 19.1243 11.4831 20.9066 12.1992 22.5342C12.9316 24.1455 13.9733 25.6348 15.3242 27.002C16.7891 28.4831 17.9528 30.0781 18.8154 31.7871C19.6781 33.4961 20.2152 35.4004 20.4268 37.5H29.9482Z" fill="#444444"/>
|
||||
<path d="M147.75 17.1875C147.757 15.7371 147.361 14.3132 146.604 13.0754C145.848 11.8377 144.763 10.8348 143.469 10.1793C142.175 9.52368 140.724 9.24124 139.279 9.36356C137.833 9.48589 136.451 10.0081 135.285 10.8719C134.12 11.7356 133.218 12.9066 132.681 14.2539C132.144 15.6011 131.992 17.0714 132.243 18.5C132.494 19.9285 133.138 21.2591 134.102 22.3425C135.066 23.4259 136.313 24.2195 137.703 24.6344C137.19 25.6774 136.396 26.5566 135.411 27.1732C134.425 27.7899 133.287 28.1195 132.125 28.125H125.875C123.561 28.1331 121.333 29.002 119.625 30.5625V15.4656C121.522 15.0784 123.208 14.0006 124.355 12.4413C125.502 10.8819 126.03 8.95199 125.835 7.02574C125.641 5.09949 124.738 3.3141 123.302 2.01572C121.866 0.717341 119.999 -0.00153351 118.062 -0.00153351C116.126 -0.00153351 114.259 0.717341 112.823 2.01572C111.387 3.3141 110.484 5.09949 110.29 7.02574C110.095 8.95199 110.623 10.8819 111.77 12.4413C112.917 14.0006 114.603 15.0784 116.5 15.4656V34.5281C114.607 34.8902 112.911 35.9327 111.733 37.4588C110.556 38.985 109.977 40.8893 110.107 42.8126C110.237 44.7359 111.066 46.5453 112.438 47.8995C113.81 49.2536 115.63 50.0589 117.555 50.1635C119.48 50.268 121.376 49.6646 122.887 48.4671C124.397 47.2695 125.418 45.5606 125.755 43.6626C126.092 41.7647 125.723 39.8089 124.718 38.1642C123.712 36.5194 122.14 35.2995 120.297 34.7344C120.811 33.6925 121.605 32.8146 122.591 32.1991C123.576 31.5836 124.713 31.255 125.875 31.25H132.125C134.075 31.241 135.973 30.6242 137.556 29.4854C139.139 28.3467 140.328 26.7427 140.956 24.8969C142.829 24.6505 144.55 23.7337 145.799 22.3163C147.048 20.8988 147.741 19.0768 147.75 17.1875ZM113.375 7.8125C113.375 6.8854 113.65 5.97912 114.165 5.20826C114.68 4.43741 115.412 3.8366 116.269 3.48181C117.125 3.12703 118.068 3.0342 118.977 3.21507C119.886 3.39593 120.721 3.84238 121.377 4.49793C122.033 5.15349 122.479 5.98872 122.66 6.89801C122.841 7.8073 122.748 8.7498 122.393 9.60633C122.038 10.4629 121.438 11.1949 120.667 11.71C119.896 12.2251 118.99 12.5 118.062 12.5C116.819 12.5 115.627 12.0061 114.748 11.1271C113.869 10.248 113.375 9.0557 113.375 7.8125ZM122.75 42.1875C122.75 43.1146 122.475 44.0209 121.96 44.7917C121.445 45.5626 120.713 46.1634 119.856 46.5182C119 46.873 118.057 46.9658 117.148 46.7849C116.239 46.6041 115.403 46.1576 114.748 45.5021C114.092 44.8465 113.646 44.0113 113.465 43.102C113.284 42.1927 113.377 41.2502 113.732 40.3937C114.087 39.5371 114.687 38.805 115.458 38.29C116.229 37.7749 117.135 37.5 118.062 37.5C119.306 37.5 120.498 37.9939 121.377 38.8729C122.256 39.752 122.75 40.9443 122.75 42.1875ZM139.937 21.875C139.01 21.875 138.104 21.6001 137.333 21.085C136.562 20.5699 135.962 19.8379 135.607 18.9813C135.252 18.1248 135.159 17.1823 135.34 16.273C135.521 15.3637 135.967 14.5285 136.623 13.8729C137.278 13.2174 138.114 12.7709 139.023 12.5901C139.932 12.4092 140.875 12.502 141.731 12.8568C142.588 13.2116 143.32 13.8124 143.835 14.5833C144.35 15.3541 144.625 16.2604 144.625 17.1875C144.625 18.4307 144.131 19.623 143.252 20.5021C142.373 21.3811 141.181 21.875 139.937 21.875Z" fill="#444444"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.125 3.125L187.25 0H202.875L206 3.125V18.75L202.875 21.875H187.25L184.125 18.75V3.125ZM187.25 3.125V18.75H202.875V3.125H187.25ZM156 31.25V12.5L159.125 9.37499H174.75L177.875 12.5V28.125L176.312 29.6875L176.313 29.6876L177.875 28.125H193.5L196.625 31.25V46.875L193.5 50H177.875H174.75V49.9997L174.75 50H159.125L156 46.875V31.25ZM159.125 46.875V31.25H174.75V46.875H159.125ZM177.875 46.875V31.25H193.5V46.875H177.875ZM159.125 28.125V12.5H174.75V28.125H159.125Z" fill="#444444"/>
|
||||
<path d="M74.7917 28.125L72.0417 30.875C71.6234 29.1911 70.6537 27.6957 69.2869 26.6269C67.9202 25.5581 66.235 24.9774 64.5 24.9774C62.765 24.9774 61.0798 25.5581 59.7131 26.6269C58.3463 27.6957 57.3766 29.1911 56.9583 30.875L54.2083 28.125L52 30.3333L55.5833 33.9167L55.125 34.375V37.5H52V40.625H55.125V40.7917C55.2844 41.8097 55.5714 42.8037 55.9792 43.75L52 47.7917L54.2083 50L57.6458 46.5625C58.4637 47.606 59.5025 48.4553 60.6875 49.0497C61.8726 49.644 63.1746 49.9686 64.5 50C65.8254 49.9686 67.1274 49.644 68.3125 49.0497C69.4976 48.4553 70.5363 47.606 71.3542 46.5625L74.7917 50L77 47.7917L73.0208 43.75C73.4337 42.7838 73.7208 41.7685 73.875 40.7292V40.5208H77V37.5H73.875V34.375L73.4167 33.9167L77 30.3333L74.7917 28.125ZM64.5 28.125C65.7432 28.125 66.9355 28.6189 67.8146 29.4979C68.6936 30.377 69.1875 31.5693 69.1875 32.8125H59.8125C59.8125 31.5693 60.3064 30.377 61.1854 29.4979C62.0645 28.6189 63.2568 28.125 64.5 28.125V28.125ZM70.75 40.625C70.5974 42.2309 69.8899 43.7335 68.7492 44.8742C67.6085 46.0149 66.1059 46.7224 64.5 46.875C62.8941 46.7224 61.3915 46.0149 60.2508 44.8742C59.1101 43.7335 58.4026 42.2309 58.25 40.625V35.9375H70.75V40.625ZM101.5 20V22.625L80.125 36.1875V32.5L97.8333 21.3125L70.75 4.16667V23.875C69.798 23.2063 68.7422 22.6995 67.625 22.375V1.3125L70 0L101.5 20Z" fill="#444444"/>
|
||||
<path d="M25.1875 53C26.7663 53 28.2881 53.2035 29.7529 53.6104C31.2178 54.0173 32.585 54.5951 33.8545 55.3438C35.1403 56.0924 36.304 56.9876 37.3457 58.0293C38.3874 59.071 39.2826 60.2347 40.0312 61.5205C40.7799 62.79 41.3577 64.1572 41.7646 65.6221C42.1716 67.0869 42.375 68.6087 42.375 70.1875C42.375 72.5475 41.9274 74.7367 41.0322 76.7549C40.137 78.7731 38.8594 80.6042 37.1992 82.248C35.8483 83.5827 34.8066 85.0719 34.0742 86.7158C33.3581 88.3597 33 90.1419 33 92.0625V98.3125C33 98.9635 32.8779 99.5739 32.6338 100.144C32.3896 100.713 32.056 101.21 31.6328 101.633C31.2096 102.056 30.7132 102.39 30.1436 102.634C29.5739 102.878 28.9635 103 28.3125 103H22.0625C21.4115 103 20.8011 102.878 20.2314 102.634C19.6618 102.39 19.1654 102.056 18.7422 101.633C18.319 101.21 17.9854 100.713 17.7412 100.144C17.4971 99.5739 17.375 98.9635 17.375 98.3125V92.0625C17.375 90.1419 17.0088 88.3597 16.2764 86.7158C15.5602 85.0719 14.5267 83.5827 13.1758 82.248C11.5156 80.6042 10.238 78.7731 9.34277 76.7549C8.44759 74.7367 8 72.5475 8 70.1875C8 68.6087 8.20345 67.0869 8.61035 65.6221C9.01725 64.1572 9.59505 62.79 10.3438 61.5205C11.0924 60.2347 11.9876 59.071 13.0293 58.0293C14.071 56.9876 15.2266 56.0924 16.4961 55.3438C17.7819 54.5951 19.1572 54.0173 20.6221 53.6104C22.0869 53.2035 23.6087 53 25.1875 53ZM28.3125 99.875C28.7357 99.875 29.1019 99.7204 29.4111 99.4111C29.7204 99.1019 29.875 98.7357 29.875 98.3125V93.625H20.5V98.3125C20.5 98.7357 20.6546 99.1019 20.9639 99.4111C21.2731 99.7204 21.6393 99.875 22.0625 99.875H28.3125ZM29.9482 90.5C30.1598 88.4004 30.6969 86.4961 31.5596 84.7871C32.4222 83.0781 33.5859 81.4831 35.0508 80.002C36.4017 78.6348 37.4352 77.1455 38.1514 75.5342C38.8838 73.9066 39.25 72.1243 39.25 70.1875C39.25 68.2507 38.8757 66.4277 38.127 64.7188C37.3945 63.0098 36.3936 61.5205 35.124 60.251C33.8545 58.9814 32.3652 57.9805 30.6562 57.248C28.9473 56.4993 27.1243 56.125 25.1875 56.125C23.2507 56.125 21.4277 56.4993 19.7188 57.248C18.0098 57.9805 16.5205 58.9814 15.251 60.251C13.9814 61.5205 12.9723 63.0098 12.2236 64.7188C11.4912 66.4277 11.125 68.2507 11.125 70.1875C11.125 72.1243 11.4831 73.9066 12.1992 75.5342C12.9316 77.1455 13.9733 78.6348 15.3242 80.002C16.7891 81.4831 17.9528 83.0781 18.8154 84.7871C19.6781 86.4961 20.2152 88.4004 20.4268 90.5H29.9482Z" fill="#2E3192"/>
|
||||
<path d="M147.75 70.1875C147.757 68.7371 147.361 67.3132 146.604 66.0755C145.848 64.8377 144.763 63.8349 143.469 63.1793C142.175 62.5237 140.724 62.2413 139.279 62.3636C137.833 62.4859 136.451 63.0082 135.285 63.8719C134.12 64.7356 133.218 65.9066 132.681 67.2539C132.144 68.6011 131.992 70.0714 132.243 71.5C132.494 72.9286 133.138 74.2591 134.102 75.3425C135.066 76.426 136.313 77.2195 137.703 77.6344C137.19 78.6774 136.396 79.5566 135.411 80.1732C134.425 80.7899 133.287 81.1195 132.125 81.125H125.875C123.561 81.1332 121.333 82.002 119.625 83.5625V68.4656C121.522 68.0784 123.208 67.0007 124.355 65.4413C125.502 63.8819 126.03 61.952 125.835 60.0258C125.641 58.0995 124.738 56.3141 123.302 55.0157C121.866 53.7174 119.999 52.9985 118.062 52.9985C116.126 52.9985 114.259 53.7174 112.823 55.0157C111.387 56.3141 110.484 58.0995 110.29 60.0258C110.095 61.952 110.623 63.8819 111.77 65.4413C112.917 67.0007 114.603 68.0784 116.5 68.4656V87.5281C114.607 87.8903 112.911 88.9327 111.733 90.4589C110.556 91.985 109.977 93.8893 110.107 95.8126C110.237 97.736 111.066 99.5453 112.438 100.899C113.81 102.254 115.63 103.059 117.555 103.163C119.48 103.268 121.376 102.665 122.887 101.467C124.397 100.27 125.418 98.5606 125.755 96.6626C126.092 94.7647 125.723 92.8089 124.718 91.1642C123.712 89.5195 122.14 88.2995 120.297 87.7344C120.811 86.6926 121.605 85.8146 122.591 85.1991C123.576 84.5837 124.713 84.255 125.875 84.25H132.125C134.075 84.241 135.973 83.6242 137.556 82.4855C139.139 81.3467 140.328 79.7428 140.956 77.8969C142.829 77.6506 144.55 76.7338 145.799 75.3163C147.048 73.8989 147.741 72.0768 147.75 70.1875ZM113.375 60.8125C113.375 59.8854 113.65 58.9791 114.165 58.2083C114.68 57.4374 115.412 56.8366 116.269 56.4818C117.125 56.1271 118.068 56.0342 118.977 56.2151C119.886 56.396 120.721 56.8424 121.377 57.498C122.033 58.1535 122.479 58.9888 122.66 59.898C122.841 60.8073 122.748 61.7498 122.393 62.6064C122.038 63.4629 121.438 64.195 120.667 64.71C119.896 65.2251 118.99 65.5 118.062 65.5C116.819 65.5 115.627 65.0062 114.748 64.1271C113.869 63.248 113.375 62.0557 113.375 60.8125ZM122.75 95.1875C122.75 96.1146 122.475 97.0209 121.96 97.7918C121.445 98.5626 120.713 99.1634 119.856 99.5182C119 99.873 118.057 99.9658 117.148 99.785C116.239 99.6041 115.403 99.1576 114.748 98.5021C114.092 97.8465 113.646 97.0113 113.465 96.102C113.284 95.1927 113.377 94.2502 113.732 93.3937C114.087 92.5372 114.687 91.8051 115.458 91.29C116.229 90.7749 117.135 90.5 118.062 90.5C119.306 90.5 120.498 90.9939 121.377 91.873C122.256 92.752 122.75 93.9443 122.75 95.1875ZM139.937 74.875C139.01 74.875 138.104 74.6001 137.333 74.085C136.562 73.57 135.962 72.8379 135.607 71.9813C135.252 71.1248 135.159 70.1823 135.34 69.273C135.521 68.3638 135.967 67.5285 136.623 66.873C137.278 66.2174 138.114 65.771 139.023 65.5901C139.932 65.4092 140.875 65.5021 141.731 65.8568C142.588 66.2116 143.32 66.8124 143.835 67.5833C144.35 68.3541 144.625 69.2604 144.625 70.1875C144.625 71.4307 144.131 72.623 143.252 73.5021C142.373 74.3812 141.181 74.875 139.937 74.875Z" fill="#F42534"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M184.125 56.125L187.25 53H202.875L206 56.125V71.75L202.875 74.875H187.25L184.125 71.75V56.125ZM187.25 56.125V71.75H202.875V56.125H187.25ZM156 84.25V65.5L159.125 62.375H174.75L177.875 65.5V81.125L176.312 82.6875L176.313 82.6876L177.875 81.125H193.5L196.625 84.25V99.875L193.5 103H177.875H174.75V103L174.75 103H159.125L156 99.875V84.25ZM159.125 99.875V84.25H174.75V99.875H159.125ZM177.875 99.875V84.25H193.5V99.875H177.875ZM159.125 81.125V65.5H174.75V81.125H159.125Z" fill="black"/>
|
||||
<path d="M74.7917 81.125L72.0417 83.875C71.6234 82.1911 70.6537 80.6957 69.2869 79.6269C67.9202 78.5581 66.235 77.9774 64.5 77.9774C62.765 77.9774 61.0798 78.5581 59.7131 79.6269C58.3463 80.6957 57.3766 82.1911 56.9583 83.875L54.2083 81.125L52 83.3333L55.5833 86.9167L55.125 87.375V90.5H52V93.625H55.125V93.7917C55.2844 94.8097 55.5714 95.8037 55.9792 96.75L52 100.792L54.2083 103L57.6458 99.5625C58.4637 100.606 59.5025 101.455 60.6875 102.05C61.8726 102.644 63.1746 102.969 64.5 103C65.8254 102.969 67.1274 102.644 68.3125 102.05C69.4976 101.455 70.5363 100.606 71.3542 99.5625L74.7917 103L77 100.792L73.0208 96.75C73.4337 95.7838 73.7208 94.7685 73.875 93.7292V93.5208H77V90.5H73.875V87.375L73.4167 86.9167L77 83.3333L74.7917 81.125ZM64.5 81.125C65.7432 81.125 66.9355 81.6189 67.8146 82.4979C68.6936 83.377 69.1875 84.5693 69.1875 85.8125H59.8125C59.8125 84.5693 60.3064 83.377 61.1854 82.4979C62.0645 81.6189 63.2568 81.125 64.5 81.125V81.125ZM70.75 93.625C70.5974 95.2309 69.8899 96.7335 68.7492 97.8742C67.6085 99.0149 66.1059 99.7224 64.5 99.875C62.8941 99.7224 61.3915 99.0149 60.2508 97.8742C59.1101 96.7335 58.4026 95.2309 58.25 93.625V88.9375H70.75V93.625ZM101.5 73V75.625L80.125 89.1875V85.5L97.8333 74.3125L70.75 57.1667V76.875C69.798 76.2063 68.7422 75.6995 67.625 75.375V54.3125L70 53L101.5 73Z" fill="#37B34A"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="206" height="104" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 14 KiB |
После Ширина: | Высота: | Размер: 13 KiB |
|
@ -2,7 +2,7 @@
|
|||
"routes": [
|
||||
{
|
||||
"route": "/docs/apis",
|
||||
"redirect": "/docs/api/v1",
|
||||
"redirect": "/docs/api/v2",
|
||||
"statusCode": 301
|
||||
}
|
||||
],
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const carousels = document.querySelectorAll(".carousel");
|
||||
carousels.forEach(function (carousel) {
|
||||
const ele = carousel.querySelector("ul");
|
||||
const amountvisible = Math.round(
|
||||
ele.offsetWidth / ele.querySelector("li:nth-child(1)").offsetWidth,
|
||||
);
|
||||
const bullets = carousel.querySelectorAll("ol li");
|
||||
const slides = carousel.querySelectorAll("ul li");
|
||||
const nextarrow = carousel.querySelector(".next");
|
||||
const prevarrow = carousel.querySelector(".prev");
|
||||
|
||||
// Initialize the carousel
|
||||
nextarrow.style.display = "block";
|
||||
prevarrow.style.display = "block";
|
||||
ele.scrollLeft = 0;
|
||||
bullets[0].classList.add("selected");
|
||||
slides[0].classList.add("selected");
|
||||
if (amountvisible > 1) {
|
||||
var removeels = carousel.querySelectorAll(
|
||||
"ol li:nth-last-child(-n + " + (amountvisible - 1) + ")",
|
||||
);
|
||||
removeels.forEach(function (removeel) {
|
||||
removeel.remove();
|
||||
});
|
||||
}
|
||||
|
||||
const setSelected = function () {
|
||||
bullets.forEach(function (bullet) {
|
||||
bullet.classList.remove("selected");
|
||||
});
|
||||
slides.forEach(function (slide) {
|
||||
slide.classList.remove("selected");
|
||||
});
|
||||
const scrolllength =
|
||||
carousel.querySelector("ul li:nth-child(2)").offsetLeft -
|
||||
carousel.querySelector("ul li:nth-child(1)").offsetLeft;
|
||||
const nthchild = Math.round(ele.scrollLeft / scrolllength + 1);
|
||||
carousel.querySelector("ol li:nth-child(" + nthchild + ")").classList.add("selected");
|
||||
carousel.querySelector("ul li:nth-child(" + nthchild + ")").classList.add("selected");
|
||||
if (carousel.parentElement.parentElement.querySelector(".dynamictitle")) {
|
||||
const title = carousel
|
||||
.querySelector("ul li:nth-child(" + nthchild + ") img")
|
||||
.getAttribute("title");
|
||||
if (title)
|
||||
carousel.parentElement.parentElement.querySelector(".dynamictitle").innerHTML =
|
||||
title;
|
||||
}
|
||||
};
|
||||
|
||||
const scrollTo = function (event) {
|
||||
event.preventDefault();
|
||||
ele.scrollLeft = ele.querySelector(this.getAttribute("href")).offsetLeft;
|
||||
};
|
||||
|
||||
const nextSlide = function () {
|
||||
if (!carousel.querySelector("ol li:last-child").classList.contains("selected")) {
|
||||
carousel
|
||||
.querySelector("ol li.selected")
|
||||
.nextElementSibling.querySelector("a")
|
||||
.click();
|
||||
} else {
|
||||
carousel.querySelector("ol li:first-child a").click();
|
||||
}
|
||||
};
|
||||
|
||||
const prevSlide = function () {
|
||||
if (!carousel.querySelector("ol li:first-child").classList.contains("selected")) {
|
||||
carousel
|
||||
.querySelector("ol li.selected")
|
||||
.previousElementSibling.querySelector("a")
|
||||
.click();
|
||||
} else {
|
||||
carousel.querySelector("ol li:last-child a").click();
|
||||
}
|
||||
};
|
||||
|
||||
const setInteracted = function () {
|
||||
ele.classList.add("interacted");
|
||||
};
|
||||
|
||||
// Attach the handlers
|
||||
ele.addEventListener("scroll", debounce(setSelected));
|
||||
ele.addEventListener("touchstart", setInteracted);
|
||||
ele.addEventListener("keydown", function (e) {
|
||||
if (e.key == "ArrowLeft") ele.classList.add("interacted");
|
||||
if (e.key == "ArrowRight") ele.classList.add("interacted");
|
||||
});
|
||||
|
||||
nextarrow.addEventListener("click", nextSlide);
|
||||
nextarrow.addEventListener("mousedown", setInteracted);
|
||||
nextarrow.addEventListener("touchstart", setInteracted);
|
||||
|
||||
prevarrow.addEventListener("click", prevSlide);
|
||||
prevarrow.addEventListener("mousedown", setInteracted);
|
||||
prevarrow.addEventListener("touchstart", setInteracted);
|
||||
|
||||
bullets.forEach(function (bullet) {
|
||||
bullet.querySelector("a").addEventListener("click", scrollTo);
|
||||
bullet.addEventListener("mousedown", setInteracted);
|
||||
bullet.addEventListener("touchstart", setInteracted);
|
||||
});
|
||||
|
||||
//setInterval for autoplay
|
||||
if (carousel.getAttribute("duration")) {
|
||||
setInterval(function () {
|
||||
if (
|
||||
ele != document.querySelector(".carousel:hover ul") &&
|
||||
ele.classList.contains("interacted") == false
|
||||
) {
|
||||
nextarrow.click();
|
||||
}
|
||||
}, carousel.getAttribute("duration"));
|
||||
}
|
||||
}); //end foreach
|
||||
}); //end onload
|
||||
|
||||
/**
|
||||
* Debounce functions for better performance
|
||||
* (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com
|
||||
* @param {Function} fn The function to debounce
|
||||
*/
|
||||
function debounce(fn) {
|
||||
// Setup a timer
|
||||
let timeout;
|
||||
// Return a function to run debounced
|
||||
return function () {
|
||||
// Setup the arguments
|
||||
let context = this;
|
||||
let args = arguments;
|
||||
// If there's a timer, cancel it
|
||||
if (timeout) {
|
||||
window.cancelAnimationFrame(timeout);
|
||||
}
|
||||
// Setup the new requestAnimationFrame()
|
||||
timeout = window.requestAnimationFrame(function () {
|
||||
fn.apply(context, args);
|
||||
});
|
||||
};
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
.home {
|
||||
/*----- Hero Section -----*/
|
||||
|
||||
overflow: hidden;
|
||||
#main-content {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
|
@ -29,7 +29,7 @@
|
|||
}
|
||||
.copy {
|
||||
@include vertical-center(0, -50%);
|
||||
top: 45%; //approximately puts download button in middle of hero image
|
||||
top: 75%; //approximately puts download button in middle of hero image
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,7 @@
|
|||
color: white;
|
||||
margin: 2.5rem 0 0 0;
|
||||
background-color: $accent-primary;
|
||||
height: 6.5rem;
|
||||
height: 7.5rem;
|
||||
img {
|
||||
top: 0;
|
||||
}
|
||||
|
@ -353,23 +353,24 @@
|
|||
font-family: $black;
|
||||
text-align: center;
|
||||
.value-prop-icon {
|
||||
// background-image: url('/assets/icons/valueprops-top-sprite.svg');
|
||||
//FF Value prop svg image url
|
||||
background-image: url('/images/valueprops-top-sprite.svg');
|
||||
background-repeat: no-repeat;
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
background-size: 20.6rem 10.4rem;
|
||||
margin: auto;
|
||||
margin-bottom: 1rem;
|
||||
&.intellisense {
|
||||
&.better-perf {
|
||||
background-position: 0 0;
|
||||
}
|
||||
&.debugging {
|
||||
&.easy-to-use {
|
||||
background-position: -5.2rem 0;
|
||||
}
|
||||
&.git {
|
||||
&.client-code {
|
||||
background-position: -10.4rem 0;
|
||||
}
|
||||
&.extensions-icon {
|
||||
&.open-source {
|
||||
background-position: -15.6rem 0;
|
||||
}
|
||||
}
|
||||
|
@ -384,16 +385,16 @@
|
|||
background: $lightgray;
|
||||
text-decoration: none;
|
||||
.value-prop-icon {
|
||||
&.intellisense {
|
||||
&.better-perf {
|
||||
background-position: 0 -5.3rem;
|
||||
}
|
||||
&.debugging {
|
||||
&.easy-to-use {
|
||||
background-position: -5.2rem -5.3rem;
|
||||
}
|
||||
&.git {
|
||||
&.client-code {
|
||||
background-position: -10.4rem -5.3rem;
|
||||
}
|
||||
&.extensions-icon {
|
||||
&.open-source {
|
||||
background-position: -15.6rem -5.3rem;
|
||||
}
|
||||
}
|
||||
|
@ -505,14 +506,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
/*----- Getting Started -----*/
|
||||
.getting-started {
|
||||
/*----- Customers -----*/
|
||||
.customers {
|
||||
padding: 50px 0;
|
||||
overflow: hidden;
|
||||
|
||||
.vscode-for {
|
||||
.title {
|
||||
height: 20.5rem; //5 times the height of the list
|
||||
h2 {
|
||||
text-align: right;
|
||||
text-align: center;
|
||||
margin-top: -1.6rem; //aligns it vertically centered to the list of langugages
|
||||
position: relative;
|
||||
top: 50%;
|
||||
|
@ -537,10 +539,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.home-languages-list-parent {
|
||||
.customers-list-parent {
|
||||
height: 20.5rem; //5 times the height of the list
|
||||
}
|
||||
.supported-languages-list {
|
||||
.customers-list {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
@ -572,8 +574,15 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.customer-stories-link {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.samplecode {
|
||||
overflow: hidden;
|
||||
// position: absolute;
|
||||
}
|
||||
.terms p {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
@ -655,4 +664,4 @@
|
|||
padding-bottom: 5%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,10 @@
|
|||
<body>
|
||||
{{- if .Site.Params.cookies -}}
|
||||
<!-- EU Cookie Compliance JS -->
|
||||
<link rel="stylesheet" href="/docs/assets/css/carousel.css">
|
||||
<script src="https://wcpstatic.microsoft.com/mscc/lib/v2/wcp-consent.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/docs/themes/thxvscode/assets/js/carousel.js"></script>
|
||||
{{- end -}}
|
||||
|
||||
<div id="main">
|
||||
|
|
|
@ -10,10 +10,9 @@
|
|||
{{- end }}
|
||||
|
||||
{{ .Content }}
|
||||
</div>
|
||||
|
||||
{{- if templates.Exists "partials/extra-foot.html" -}}
|
||||
{{ partial "extra-foot.html" . }}
|
||||
{{- end }}
|
||||
|
||||
{{ end }}
|
||||
{{ end }}
|
|
@ -5,7 +5,9 @@
|
|||
<body>
|
||||
{{- if .Site.Params.cookies -}}
|
||||
<!-- EU Cookie Compliance JS -->
|
||||
<link rel="stylesheet" href="/docs/assets/css/carousel.css">
|
||||
<script src="https://wcpstatic.microsoft.com/mscc/lib/v2/wcp-consent.js"></script>
|
||||
<script type="text/javascript" src="/docs/themes/thxvscode/assets/js/carousel.js"></script>
|
||||
{{- end -}}
|
||||
|
||||
<div id="main">
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
role="button" tabindex="0">Follow
|
||||
@{{.Site.Params.twitterHandle}}</a>
|
||||
</li>
|
||||
|
||||
<script>
|
||||
function followOnTwitter() {
|
||||
var windowFeatures = "location=yes,height=600,width=550,scrollbars=yes,status=yes";
|
||||
|
@ -20,6 +19,11 @@
|
|||
</script>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- <div class="center col-md-3 col-md-offset-4">
|
||||
<ul class="links">
|
||||
<li class="text-center">Made with ❤️ by Fluid Team</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
<div class="right col-md-5 col-md-offset-4">
|
||||
<ul class="links">
|
||||
<li><a id="footer-privacy-link" href="https://privacy.microsoft.com/privacystatement"
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<meta itemprop="datePublished" content="{{ now.Format "2006-01-02" }}">
|
||||
|
||||
<!-- sections.meta -->
|
||||
{{ $summary := .Params.summary | plainify | truncate 140 }}
|
||||
{{ $summary := .Params.summary | plainify | truncate 180 }}
|
||||
{{ if eq $summary ""}}
|
||||
{{ $summary = .Title }}
|
||||
{{ end }}
|
||||
|
@ -66,4 +66,4 @@
|
|||
<meta property="og:title" content="{{.Title}}" />
|
||||
<meta property="og:description" content="{{ $summary }}" />
|
||||
|
||||
</head>
|
||||
</head>
|
|
@ -25,21 +25,37 @@
|
|||
<div class="jumbotron {{$class}}">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-4 copy">
|
||||
<h1>{{$lead}}</h1>
|
||||
<div class="lead">
|
||||
<p>{{ $subText }}</p>
|
||||
<div class="col-md-6 copy">
|
||||
<div class="row">
|
||||
<h1>{{$lead}}</h1>
|
||||
<div class="lead">
|
||||
<p>{{ $subText }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="download-buttons" class="download-hero alt-downloads"></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="hero-img" id="jumbotron-{{$uniqueImgID}}" style="background-image: url('{{$imgURL}}')">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="ratio ratio-16x9">
|
||||
<iframe width="590" height="300" src="{{$imgURL}}" title="Fluid Framework video"></iframe>
|
||||
</div>
|
||||
<!-- <div class="hero-img" id="jumbotron-{{$uniqueImgID}}" style="background-image: url('{{$imgURL}}')">
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="container">
|
||||
<div class="row">
|
||||
<div class="download-hero primary-buttons">
|
||||
<div class="col-md-4">
|
||||
<a class="link-button dlink" href="/docs/start/tutorial">Get Started</a>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<a class="link-button dlink" href="/docs/start/tutorial">Demo</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
{{ else }}
|
||||
<div class="jumbotron {{$class}}">
|
||||
<div class="container">
|
||||
|
@ -53,4 +69,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|